赛事判断
This commit is contained in:
parent
2ee874554d
commit
fc1d85449d
@ -382,6 +382,7 @@ public class CertificateGenerateService : IDynamicApiController, ITransient
|
|||||||
private async Task<DocumentData> ExtractDocumentData(Stream docStream)
|
private async Task<DocumentData> ExtractDocumentData(Stream docStream)
|
||||||
{
|
{
|
||||||
var documentData = new DocumentData();
|
var documentData = new DocumentData();
|
||||||
|
var processedTexts = new HashSet<string>(); // 记录已处理的文本,避免重复
|
||||||
|
|
||||||
using var wordprocessingDocument = WordprocessingDocument.Open(docStream, false);
|
using var wordprocessingDocument = WordprocessingDocument.Open(docStream, false);
|
||||||
var body = wordprocessingDocument.MainDocumentPart?.Document?.Body;
|
var body = wordprocessingDocument.MainDocumentPart?.Document?.Body;
|
||||||
@ -392,11 +393,19 @@ public class CertificateGenerateService : IDynamicApiController, ITransient
|
|||||||
if (body != null)
|
if (body != null)
|
||||||
{
|
{
|
||||||
// 首先处理 Drawing 对象(浮于文字上方的文本框)
|
// 首先处理 Drawing 对象(浮于文字上方的文本框)
|
||||||
ExtractDrawingObjects(body, documentData);
|
ExtractDrawingObjects(body, documentData, processedTexts);
|
||||||
|
|
||||||
// 提取段落(包含位置信息)
|
// 提取段落(包含位置信息),但跳过包含Drawing对象的段落(避免重复)
|
||||||
foreach (var paragraph in body.Elements<Paragraph>())
|
foreach (var paragraph in body.Elements<Paragraph>())
|
||||||
{
|
{
|
||||||
|
// 检查段落是否包含 Drawing 对象,如果是则跳过(已在 ExtractDrawingObjects 中处理)
|
||||||
|
var hasDrawing = paragraph.Descendants<DocumentFormat.OpenXml.Wordprocessing.Drawing>().Any();
|
||||||
|
if (hasDrawing)
|
||||||
|
{
|
||||||
|
_logger.LogDebug("跳过包含 Drawing 对象的段落");
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
var paragraphText = paragraph.InnerText?.Trim();
|
var paragraphText = paragraph.InnerText?.Trim();
|
||||||
if (!string.IsNullOrEmpty(paragraphText))
|
if (!string.IsNullOrEmpty(paragraphText))
|
||||||
{
|
{
|
||||||
@ -414,6 +423,13 @@ public class CertificateGenerateService : IDynamicApiController, ITransient
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 检查是否已经处理过相同文本,避免重复
|
||||||
|
if (processedTexts.Contains(cleanedText))
|
||||||
|
{
|
||||||
|
_logger.LogDebug("跳过重复文本: {Text}", cleanedText);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
var paragraphData = new ParagraphData
|
var paragraphData = new ParagraphData
|
||||||
{
|
{
|
||||||
Text = cleanedText,
|
Text = cleanedText,
|
||||||
@ -431,6 +447,7 @@ public class CertificateGenerateService : IDynamicApiController, ITransient
|
|||||||
cleanedText, paragraphData.PositionX, paragraphData.PositionY);
|
cleanedText, paragraphData.PositionX, paragraphData.PositionY);
|
||||||
|
|
||||||
documentData.Paragraphs.Add(paragraphData);
|
documentData.Paragraphs.Add(paragraphData);
|
||||||
|
processedTexts.Add(cleanedText);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -658,7 +675,7 @@ public class CertificateGenerateService : IDynamicApiController, ITransient
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// 提取 Drawing 对象(浮于文字上方的文本框)
|
/// 提取 Drawing 对象(浮于文字上方的文本框)
|
||||||
/// </summary>
|
/// </summary>
|
||||||
private void ExtractDrawingObjects(Body body, DocumentData documentData)
|
private void ExtractDrawingObjects(Body body, DocumentData documentData, HashSet<string> processedTexts = null)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
@ -670,7 +687,7 @@ public class CertificateGenerateService : IDynamicApiController, ITransient
|
|||||||
|
|
||||||
foreach (var drawing in drawings)
|
foreach (var drawing in drawings)
|
||||||
{
|
{
|
||||||
ExtractTextFromDrawing(drawing, documentData);
|
ExtractTextFromDrawing(drawing, documentData, processedTexts);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -683,7 +700,7 @@ public class CertificateGenerateService : IDynamicApiController, ITransient
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// 从 Drawing 对象中提取文本和位置信息
|
/// 从 Drawing 对象中提取文本和位置信息
|
||||||
/// </summary>
|
/// </summary>
|
||||||
private void ExtractTextFromDrawing(DocumentFormat.OpenXml.Wordprocessing.Drawing drawing, DocumentData documentData)
|
private void ExtractTextFromDrawing(DocumentFormat.OpenXml.Wordprocessing.Drawing drawing, DocumentData documentData, HashSet<string> processedTexts = null)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
@ -714,6 +731,13 @@ public class CertificateGenerateService : IDynamicApiController, ITransient
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 检查是否已经处理过相同文本,避免重复
|
||||||
|
if (processedTexts != null && processedTexts.Contains(cleanedText))
|
||||||
|
{
|
||||||
|
_logger.LogDebug("跳过 Drawing 对象中的重复文本: {Text}", cleanedText);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
var paragraphData = new ParagraphData
|
var paragraphData = new ParagraphData
|
||||||
{
|
{
|
||||||
Text = cleanedText,
|
Text = cleanedText,
|
||||||
@ -731,6 +755,10 @@ public class CertificateGenerateService : IDynamicApiController, ITransient
|
|||||||
cleanedText, paragraphData.PositionX, paragraphData.PositionY);
|
cleanedText, paragraphData.PositionX, paragraphData.PositionY);
|
||||||
|
|
||||||
documentData.Paragraphs.Add(paragraphData);
|
documentData.Paragraphs.Add(paragraphData);
|
||||||
|
if (processedTexts != null)
|
||||||
|
{
|
||||||
|
processedTexts.Add(cleanedText);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1033,7 +1061,7 @@ public class CertificateGenerateService : IDynamicApiController, ITransient
|
|||||||
.FitArea();
|
.FitArea();
|
||||||
}
|
}
|
||||||
|
|
||||||
// 使用 Column 来放置所有内容
|
// 使用 Column 来放置所有内容,但使用 Translate 而非 Padding 定位
|
||||||
page.Content().Column(column =>
|
page.Content().Column(column =>
|
||||||
{
|
{
|
||||||
// 根据段落信息进行定位(使用从Word文档提取的位置信息)
|
// 根据段落信息进行定位(使用从Word文档提取的位置信息)
|
||||||
@ -1046,14 +1074,14 @@ public class CertificateGenerateService : IDynamicApiController, ITransient
|
|||||||
_logger.LogDebug("处理段落: Text={Text}, X={X}, Y={Y}, FontSize={FontSize}, Bold={IsBold}",
|
_logger.LogDebug("处理段落: Text={Text}, X={X}, Y={Y}, FontSize={FontSize}, Bold={IsBold}",
|
||||||
paragraph.Text, paragraph.PositionX, paragraph.PositionY, fontSize, isBold);
|
paragraph.Text, paragraph.PositionX, paragraph.PositionY, fontSize, isBold);
|
||||||
|
|
||||||
// 直接使用从Word文档提取的位置信息
|
// 直接使用从Word文档提取的位置信息,并增加110个单位进行调整
|
||||||
float x = (float)(paragraph.PositionX ?? 50);
|
float x = (float)(paragraph.PositionX ?? 50) + 90;
|
||||||
float y = (float)(paragraph.PositionY ?? 50);
|
float y = (float)(paragraph.PositionY ?? 50) + 50;
|
||||||
|
|
||||||
_logger.LogDebug("最终位置 - X={X}, Y={Y}", x, y);
|
_logger.LogDebug("最终位置 - X={X}, Y={Y}", x, y);
|
||||||
|
|
||||||
// 使用 Padding 来定位文本
|
// 使用 Translate 而非 Padding 来定位,避免流式布局累加导致分页
|
||||||
var textElement = column.Item().PaddingLeft(x).PaddingTop(y).Text(paragraph.Text)
|
var textElement = column.Item().TranslateX(x).TranslateY(y).Text(paragraph.Text)
|
||||||
.FontSize((float)fontSize)
|
.FontSize((float)fontSize)
|
||||||
.FontColor(QuestPDF.Helpers.Colors.Black)
|
.FontColor(QuestPDF.Helpers.Colors.Black)
|
||||||
.AlignLeft();
|
.AlignLeft();
|
||||||
|
|||||||
@ -1131,41 +1131,45 @@ public class UserEventRegistrationService : IDynamicApiController, ITransient
|
|||||||
// 判断是否为团队项目
|
// 判断是否为团队项目
|
||||||
var isTeamProject = project.IsTeamProject();
|
var isTeamProject = project.IsTeamProject();
|
||||||
|
|
||||||
// 计算分配的人数(去重)
|
// 对每个分配的组别进行独立验证
|
||||||
var totalAssignedMembers = input.GroupMembers
|
foreach (var assignedGroup in assignedProjectGroups)
|
||||||
.Where(g => assignedProjectGroups.Select(pg => pg.Id).Contains(g.GroupId))
|
|
||||||
.SelectMany(g => g.MemberIds)
|
|
||||||
.Distinct()
|
|
||||||
.Count();
|
|
||||||
|
|
||||||
if (project.CompletionCount > 0)
|
|
||||||
{
|
{
|
||||||
if (totalAssignedMembers < project.CompletionCount)
|
// 找到该组别的队员分配
|
||||||
|
var groupMemberAssignment = input.GroupMembers.FirstOrDefault(gm => gm.GroupId == assignedGroup.Id);
|
||||||
|
if (groupMemberAssignment == null) continue;
|
||||||
|
|
||||||
|
// 计算该组别的分配人数(不跨组别,也不跨项目去重)
|
||||||
|
var assignedCount = groupMemberAssignment.MemberIds?.Distinct().Count() ?? 0;
|
||||||
|
|
||||||
|
if (project.CompletionCount > 0)
|
||||||
{
|
{
|
||||||
result.HasError = true;
|
if (assignedCount < project.CompletionCount)
|
||||||
result.Errors.Add(new ProjectCompletionError
|
|
||||||
{
|
{
|
||||||
ProjectId = eventProject.Id,
|
result.HasError = true;
|
||||||
ProjectName = project.Name ?? "未知项目",
|
result.Errors.Add(new ProjectCompletionError
|
||||||
ErrorType = "Insufficient",
|
{
|
||||||
ErrorMessage = isTeamProject
|
ProjectId = eventProject.Id,
|
||||||
? $"项目\"{project.Name}\"要求完成人数为{project.CompletionCount}人,当前只分配了{totalAssignedMembers}人"
|
ProjectName = project.Name ?? "未知项目",
|
||||||
: $"项目\"{project.Name}\"要求完成人数为{project.CompletionCount}人,当前只分配了{totalAssignedMembers}人"
|
ErrorType = "Insufficient",
|
||||||
});
|
ErrorMessage = isTeamProject
|
||||||
}
|
? $"项目\"{project.Name}\"的组别\"{assignedGroup.GroupName}\"要求完成人数为{project.CompletionCount}人,当前只分配了{assignedCount}人,请补充队员"
|
||||||
else if (totalAssignedMembers >= project.CompletionCount)
|
: $"项目\"{project.Name}\"的组别\"{assignedGroup.GroupName}\"要求完成人数为{project.CompletionCount}人,当前只分配了{assignedCount}人,请补充队员"
|
||||||
{
|
});
|
||||||
// 只要达到或超过完成人数就提示超限(特别是个人项目)
|
}
|
||||||
result.HasError = true;
|
else if (assignedCount > project.CompletionCount)
|
||||||
result.Errors.Add(new ProjectCompletionError
|
|
||||||
{
|
{
|
||||||
ProjectId = eventProject.Id,
|
// 只要达到或超过完成人数就提示超限(特别是个人项目)
|
||||||
ProjectName = project.Name ?? "未知项目",
|
result.HasError = true;
|
||||||
ErrorType = "Excessive",
|
result.Errors.Add(new ProjectCompletionError
|
||||||
ErrorMessage = isTeamProject
|
{
|
||||||
? $"项目\"{project.Name}\"要求完成人数为{project.CompletionCount}人,当前分配了{totalAssignedMembers}人,人数超额"
|
ProjectId = eventProject.Id,
|
||||||
: $"项目\"{project.Name}\"要求完成人数为{project.CompletionCount}人,当前分配了{totalAssignedMembers}人,人数超额"
|
ProjectName = project.Name ?? "未知项目",
|
||||||
});
|
ErrorType = "Excessive",
|
||||||
|
ErrorMessage = isTeamProject
|
||||||
|
? $"项目\"{project.Name}\"的组别\"{assignedGroup.GroupName}\"要求完成人数为{project.CompletionCount}人,当前分配了{assignedCount}人,人数超额,请移除多余队员"
|
||||||
|
: $"项目\"{project.Name}\"的组别\"{assignedGroup.GroupName}\"要求完成人数为{project.CompletionCount}人,当前分配了{assignedCount}人,人数超额,请移除多余队员"
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -852,12 +852,12 @@
|
|||||||
清理段落文本,移除不需要的内容
|
清理段落文本,移除不需要的内容
|
||||||
</summary>
|
</summary>
|
||||||
</member>
|
</member>
|
||||||
<member name="M:YD_Event.Application.Certificate.CertificateGenerateService.ExtractDrawingObjects(DocumentFormat.OpenXml.Wordprocessing.Body,YD_Event.Application.Certificate.DocumentData)">
|
<member name="M:YD_Event.Application.Certificate.CertificateGenerateService.ExtractDrawingObjects(DocumentFormat.OpenXml.Wordprocessing.Body,YD_Event.Application.Certificate.DocumentData,System.Collections.Generic.HashSet{System.String})">
|
||||||
<summary>
|
<summary>
|
||||||
提取 Drawing 对象(浮于文字上方的文本框)
|
提取 Drawing 对象(浮于文字上方的文本框)
|
||||||
</summary>
|
</summary>
|
||||||
</member>
|
</member>
|
||||||
<member name="M:YD_Event.Application.Certificate.CertificateGenerateService.ExtractTextFromDrawing(DocumentFormat.OpenXml.Wordprocessing.Drawing,YD_Event.Application.Certificate.DocumentData)">
|
<member name="M:YD_Event.Application.Certificate.CertificateGenerateService.ExtractTextFromDrawing(DocumentFormat.OpenXml.Wordprocessing.Drawing,YD_Event.Application.Certificate.DocumentData,System.Collections.Generic.HashSet{System.String})">
|
||||||
<summary>
|
<summary>
|
||||||
从 Drawing 对象中提取文本和位置信息
|
从 Drawing 对象中提取文本和位置信息
|
||||||
</summary>
|
</summary>
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user