yuanrf 10 часов назад
Родитель
Сommit
720e5243bc

+ 471 - 0
OASystem/OASystem.Api/Controllers/GroupsController.cs

@@ -32311,7 +32311,478 @@ ORDER BY
         }
 
 
+        [HttpPost]
+        public async Task<IActionResult> InspectionReportFileDown(InspectionReportFileDownDto Dto)
+        {
+            var di = _sqlSugar.Queryable<Grp_DelegationInfo>()
+                .Where(x => x.IsDel == 0 && x.Id == Dto.Diid)
+                .First();
+
+            if (di == null)
+            {
+                return Ok(JsonView(false, "团组信息不存在!"));
+            }
+
+            //书签dic
+            var bookmarks = new Dictionary<string, string>();
+            bookmarks.Add("TeamName", di.TeamName);
+            bookmarks.Add("TeamName1", di.TeamName);
+            bookmarks.Add("ClientUnit", di.ClientUnit);
+            bookmarks.Add("ClientUnit1", di.ClientUnit);
+            bookmarks.Add("thisTime", DateTime.Now.ToString("yyyy年MM月dd日"));
+
+            //读取word模板
+            var templatePath = $"{AppSettingsHelper.Get("WordBasePath")}/template/活动验收报告.docx";
+            var doc = new Document(templatePath);
+
+            var chiList = _sqlSugar.Queryable<Grp_ConferenceAffairsCostChild>()
+                .Where(x => x.IsDel == 0 && x.Diid == Dto.Diid)
+                .Select(x => new
+                {
+                    x.Index,
+                    x.PriceName,
+                    PriceType = SqlFunc.Subqueryable<Sys_SetData>().Where(y => y.IsDel == 0 && y.Id == x.PriceType).Select(y => y.Name),
+                    x.Count,
+                    x.Remark,
+                    x.Imgs
+                })
+                .OrderBy(x => x.Index)
+                .ToList();
+
+            //获取word所有表格
+            var allTables = doc.GetChildNodes(NodeType.Table, true);
+            //获取word第一个表格
+            var table = allTables[0] as Aspose.Words.Tables.Table;
+
+            //内容行索引
+            var startIndex = 2;
+
+            var copyRow = table.Rows[startIndex].Clone(true);
+
+            for (int i = 0; i < chiList.Count; i++)
+            {
+                var chi = chiList[i];
+
+                //插入复制的行(从第2次开始插入新行,第1次使用模板行)
+                if (i > 0)
+                {
+                    var newRow = copyRow.Clone(true) as Aspose.Words.Tables.Row;
+                    table.Rows.Insert(startIndex, newRow);
+                }
+
+                //word 表格 赋值
+                var row = table.Rows[startIndex];
+                row.Cells[0].FirstParagraph.Runs.Clear();
+                row.Cells[0].FirstParagraph.AppendChild(new Run(doc, (i + 1).ToString()));
+
+                row.Cells[1].FirstParagraph.Runs.Clear();
+                row.Cells[1].FirstParagraph.AppendChild(new Run(doc, chi.PriceName));
+
+                row.Cells[2].FirstParagraph.Runs.Clear();
+                row.Cells[2].FirstParagraph.AppendChild(new Run(doc, chi.PriceType));
+
+                row.Cells[3].FirstParagraph.Runs.Clear();
+                row.Cells[3].FirstParagraph.AppendChild(new Run(doc, chi.Count.ToString()));
+
+                row.Cells[4].FirstParagraph.Runs.Clear();
+                row.Cells[4].FirstParagraph.AppendChild(new Run(doc, chi.Remark));
+
+                if (!string.IsNullOrWhiteSpace(chi.Imgs))
+                {
+                    var imgs = chi.Imgs.Split(',').Where(x => !string.IsNullOrWhiteSpace(x)).ToArray();
+
+                    if (imgs.Length > 0)
+                    {
+                        // 获取图片基础路径配置
+                        string baseUrl = AppSettingsHelper.Get("ConferenceCostImageBaseUrl");
+                        string basePath = AppSettingsHelper.Get("ConferenceCostImageBasePath");
+
+                        // 按图片方向分类,同时缓存图片字节数据
+                        var imageInfos = new List<(string url, bool isWide, int width, int height, byte[] imageData)>();
+
+                        _logger.LogInformation($"开始处理图片,配置 - BaseUrl: {baseUrl}, BasePath: {basePath}, 索引: {chi.Index}");
+
+                        using (var httpClient = new HttpClient())
+                        {
+                            httpClient.Timeout = TimeSpan.FromSeconds(30);
+
+                            foreach (var imgUrl in imgs)
+                            {
+                                try
+                                {
+                                    string fullUrl = imgUrl;
+                                    string localPath = "";
+
+                                    // 判断是否为完整URL
+                                    if (imgUrl.StartsWith("http://") || imgUrl.StartsWith("https://"))
+                                    {
+                                        fullUrl = imgUrl;
+                                        // 尝试从URL转换为本地路径
+                                        if (imgUrl.Contains("/child/"))
+                                        {
+                                            var pathPart = imgUrl.Substring(imgUrl.IndexOf("/child/"));
+                                            localPath = Path.Combine(basePath, pathPart.TrimStart('/').Replace("/", "\\"));
+                                        }
+                                    }
+                                    else
+                                    {
+                                        // 文件名,构造本地路径和完整URL
+                                        localPath = Path.Combine(basePath, "child", chi.Index.ToString(), imgUrl);
+                                        fullUrl = $"{baseUrl.TrimEnd('/')}/child/{chi.Index}/{imgUrl}";
+                                    }
+
+                                    _logger.LogInformation($"处理图片 [{imgUrl}] - 本地路径: {localPath}, URL: {fullUrl}");
+
+                                    // 优先使用本地文件,如果不存在则尝试下载
+                                    byte[] imageBytes = null;
+
+                                    if (!string.IsNullOrEmpty(localPath) && System.IO.File.Exists(localPath))
+                                    {
+                                        imageBytes = System.IO.File.ReadAllBytes(localPath);
+                                        _logger.LogInformation($"从本地加载成功,大小: {imageBytes.Length} 字节");
+                                    }
+                                    else
+                                    {
+                                        // 从URL下载图片
+                                        try
+                                        {
+                                            _logger.LogInformation($"本地文件不存在,尝试从URL下载: {fullUrl}");
+                                            imageBytes = await httpClient.GetByteArrayAsync(fullUrl);
+                                            _logger.LogInformation($"从URL下载成功,大小: {imageBytes.Length} 字节");
+                                        }
+                                        catch (Exception ex)
+                                        {
+                                            _logger.LogWarning($"下载图片失败: {fullUrl}, 错误: {ex.Message}");
+                                            continue;
+                                        }
+                                    }
+
+                                    if (imageBytes != null && imageBytes.Length > 0)
+                                    {
+                                        // 获取图片尺寸
+                                        using (var ms = new MemoryStream(imageBytes))
+                                        {
+                                            using (var image = System.Drawing.Image.FromStream(ms))
+                                            {
+                                                bool isWide = image.Width >= image.Height;
+                                                // 缓存图片数据,避免后续重复加载
+                                                imageInfos.Add((imgUrl, isWide, image.Width, image.Height, imageBytes));
+                                                _logger.LogInformation($"图片分析完成 - 宽度: {image.Width}px, 高度: {image.Height}px, 类型: {(isWide ? "横图" : "竖图")}");
+                                            }
+                                        }
+                                    }
+                                }
+                                catch (Exception ex)
+                                {
+                                    _logger.LogError(ex, $"处理图片失败: {imgUrl}");
+                                    continue;
+                                }
+                            }
+                        }
+
+                        _logger.LogInformation($"图片处理完成,成功加载 {imageInfos.Count} 张图片");
+
+                        // 插入图片行
+                        if (imageInfos.Count > 0)
+                        {
+                            var builder = new DocumentBuilder(doc);
+                            // 从数据模板行获取正确的列数,而不是标题行(标题行可能是合并单元格)
+                            int totalColumns = table.Rows[startIndex].Cells.Count;
+
+                            _logger.LogInformation($"表格总列数: {totalColumns}(从第{startIndex}行获取)");
+
+                            for (int imgIndex = 0; imgIndex < imageInfos.Count;)
+                            {
+                                var currentImg = imageInfos[imgIndex];
+
+                                // 在当前行后插入新行(使用复制的模板行)
+                                var newRow = copyRow.Clone(true) as Aspose.Words.Tables.Row;
+                                table.Rows.Insert(startIndex + 1, newRow);
+                                startIndex++; // 更新startIndex,因为插入了新行
+
+                                // 重置所有单元格的合并状态(关键:清除克隆行的原有格式)
+                                for (int col = 0; col < totalColumns; col++)
+                                {
+                                    if (col < newRow.Cells.Count)
+                                    {
+                                        newRow.Cells[col].CellFormat.HorizontalMerge = CellMerge.None;
+                                        newRow.Cells[col].CellFormat.VerticalMerge = CellMerge.None;
+                                    }
+                                }
+
+                                if (currentImg.isWide)
+                                {
+                                    _logger.LogInformation($"开始插入宽图 [{currentImg.url}],宽度: {currentImg.width}px");
+
+                                    // 宽图:先设置所有单元格的合并状态
+                                    for (int col = 0; col < totalColumns; col++)
+                                    {
+                                        if (col < newRow.Cells.Count)
+                                        {
+                                            var cell = newRow.Cells[col];
+                                            cell.RemoveAllChildren();
+
+                                            if (col == 0)
+                                            {
+                                                cell.CellFormat.HorizontalMerge = CellMerge.First;
+                                            }
+                                            else
+                                            {
+                                                cell.CellFormat.HorizontalMerge = CellMerge.Previous;
+                                            }
+                                            cell.CellFormat.PreferredWidth = PreferredWidth.Auto;
+                                        }
+                                    }
+
+                                    // 然后在第一个单元格插入图片
+                                    var firstCell = newRow.Cells[0];
+                                    var para = new Paragraph(doc);
+                                    para.ParagraphFormat.Alignment = ParagraphAlignment.Center;
+                                    firstCell.AppendChild(para);
+                                    builder.MoveTo(para);
+
+                                    try
+                                    {
+                                        // 使用缓存的图片数据
+                                        byte[] imageBytes = currentImg.imageData;
+
+                                        if (imageBytes != null && imageBytes.Length > 0)
+                                        {
+                                            using (var imgStream = new MemoryStream(imageBytes))
+                                            {
+                                                // 插入图片,设置合理的宽度和最大高度
+                                                var shape = builder.InsertImage(imgStream);
 
+                                                // 使用预先获取的原始尺寸
+                                                double originalWidth = currentImg.width;
+                                                double originalHeight = currentImg.height;
+
+                                                // 设置最大宽度(约表格宽度的85%,避免超出)
+                                                double maxWidth = 380;
+                                                double maxHeight = 300; // 限制最大高度,避免图片过高
+
+                                                // 计算缩放比例
+                                                double widthScale = originalWidth > maxWidth ? maxWidth / originalWidth : 1;
+                                                double heightScale = originalHeight > maxHeight ? maxHeight / originalHeight : 1;
+                                                double scale = Math.Min(widthScale, heightScale);
+
+                                                shape.Width = originalWidth * scale;
+                                                shape.Height = originalHeight * scale;
+
+                                                _logger.LogInformation($"宽图插入成功,原始尺寸: {originalWidth}x{originalHeight}, 缩放后: {shape.Width:F0}x{shape.Height:F0},已合并 {totalColumns} 个单元格");
+                                            }
+                                        }
+                                        else
+                                        {
+                                            _logger.LogWarning($"图片数据为空");
+                                            para.AppendChild(new Run(doc, "[图片数据为空]"));
+                                        }
+                                    }
+                                    catch (Exception ex)
+                                    {
+                                        _logger.LogError(ex, $"插入宽图失败: {currentImg.url}");
+                                        para.AppendChild(new Run(doc, "[图片加载失败]"));
+                                    }
+
+                                    imgIndex++; // 处理下一张图片
+                                }
+                                else
+                                {
+                                    _logger.LogInformation($"开始插入高图 [{currentImg.url}],高度: {currentImg.height}px");
+
+                                    // 高图:合并一半单元格
+                                    int halfColumns = totalColumns / 2;
+                                    _logger.LogInformation($"高图模式 - 前半部分列数: {halfColumns}, 后半部分列数: {totalColumns - halfColumns}");
+
+                                    // 先设置前一半单元格的合并状态
+                                    for (int col = 0; col < halfColumns; col++)
+                                    {
+                                        if (col < newRow.Cells.Count)
+                                        {
+                                            var cell = newRow.Cells[col];
+                                            cell.RemoveAllChildren();
+
+                                            if (col == 0)
+                                            {
+                                                cell.CellFormat.HorizontalMerge = CellMerge.First;
+                                            }
+                                            else
+                                            {
+                                                cell.CellFormat.HorizontalMerge = CellMerge.Previous;
+                                            }
+                                            cell.CellFormat.PreferredWidth = PreferredWidth.Auto;
+                                        }
+                                    }
+
+                                    // 设置后一半单元格的合并状态
+                                    for (int col = halfColumns; col < totalColumns; col++)
+                                    {
+                                        if (col < newRow.Cells.Count)
+                                        {
+                                            var cell = newRow.Cells[col];
+                                            cell.RemoveAllChildren();
+
+                                            if (col == halfColumns)
+                                            {
+                                                cell.CellFormat.HorizontalMerge = CellMerge.First;
+                                            }
+                                            else
+                                            {
+                                                cell.CellFormat.HorizontalMerge = CellMerge.Previous;
+                                            }
+                                            cell.CellFormat.PreferredWidth = PreferredWidth.Auto;
+                                        }
+                                    }
+
+                                    // 在第一个单元格插入第一张高图
+                                    var firstCell = newRow.Cells[0];
+                                    var para1 = new Paragraph(doc);
+                                    para1.ParagraphFormat.Alignment = ParagraphAlignment.Center;
+                                    firstCell.AppendChild(para1);
+                                    builder.MoveTo(para1);
+
+                                    try
+                                    {
+                                        // 使用缓存的图片数据
+                                        byte[] imageBytes = currentImg.imageData;
+
+                                        if (imageBytes != null && imageBytes.Length > 0)
+                                        {
+                                            using (var imgStream = new MemoryStream(imageBytes))
+                                            {
+                                                var shape = builder.InsertImage(imgStream);
+
+                                                // 使用预先获取的原始尺寸
+                                                double originalWidth = currentImg.width;
+                                                double originalHeight = currentImg.height;
+
+                                                // 设置最大宽度和高度(约表格一半宽度)
+                                                double maxWidth = 180;
+                                                double maxHeight = 300; // 限制最大高度
+
+                                                // 计算缩放比例
+                                                double widthScale = originalWidth > maxWidth ? maxWidth / originalWidth : 1;
+                                                double heightScale = originalHeight > maxHeight ? maxHeight / originalHeight : 1;
+                                                double scale = Math.Min(widthScale, heightScale);
+
+                                                shape.Width = originalWidth * scale;
+                                                shape.Height = originalHeight * scale;
+
+                                                _logger.LogInformation($"第一张高图插入成功,原始尺寸: {originalWidth}x{originalHeight}, 缩放后: {shape.Width:F0}x{shape.Height:F0},已合并前 {halfColumns} 个单元格");
+                                            }
+                                        }
+                                        else
+                                        {
+                                            _logger.LogWarning($"图片数据为空");
+                                            para1.AppendChild(new Run(doc, "[图片数据为空]"));
+                                        }
+                                    }
+                                    catch (Exception ex)
+                                    {
+                                        _logger.LogError(ex, $"插入高图失败: {currentImg.url}");
+                                        para1.AppendChild(new Run(doc, "[图片加载失败]"));
+                                    }
+
+                                    imgIndex++; // 第一张高图已处理
+
+                                    // 检查是否还有下一张高图,如果有则插入到后一半单元格
+                                    if (imgIndex < imageInfos.Count && !imageInfos[imgIndex].isWide)
+                                    {
+                                        var secondCell = newRow.Cells[halfColumns];
+                                        var para2 = new Paragraph(doc);
+                                        para2.ParagraphFormat.Alignment = ParagraphAlignment.Center;
+                                        secondCell.AppendChild(para2);
+                                        builder.MoveTo(para2);
+
+                                        try
+                                        {
+                                            var nextImg = imageInfos[imgIndex];
+                                            _logger.LogInformation($"开始插入第二张高图 [{nextImg.url}]");
+
+                                            // 使用缓存的图片数据
+                                            byte[] imageBytes = nextImg.imageData;
+
+                                            if (imageBytes != null && imageBytes.Length > 0)
+                                            {
+                                                using (var imgStream = new MemoryStream(imageBytes))
+                                                {
+                                                    var shape = builder.InsertImage(imgStream);
+
+                                                    // 使用预先获取的原始尺寸
+                                                    double originalWidth = nextImg.width;
+                                                    double originalHeight = nextImg.height;
+
+                                                    // 设置最大宽度和高度
+                                                    double maxWidth = 180;
+                                                    double maxHeight = 300;
+
+                                                    // 计算缩放比例
+                                                    double widthScale = originalWidth > maxWidth ? maxWidth / originalWidth : 1;
+                                                    double heightScale = originalHeight > maxHeight ? maxHeight / originalHeight : 1;
+                                                    double scale = Math.Min(widthScale, heightScale);
+
+                                                    shape.Width = originalWidth * scale;
+                                                    shape.Height = originalHeight * scale;
+
+                                                    _logger.LogInformation($"第二张高图插入成功,原始尺寸: {originalWidth}x{originalHeight}, 缩放后: {shape.Width:F0}x{shape.Height:F0},已合并后 {totalColumns - halfColumns} 个单元格");
+                                                }
+                                            }
+                                            else
+                                            {
+                                                _logger.LogWarning($"第二张高图数据为空");
+                                                para2.AppendChild(new Run(doc, "[图片数据为空]"));
+                                            }
+
+                                            imgIndex++; // 第二张高图已处理
+                                        }
+                                        catch (Exception ex)
+                                        {
+                                            _logger.LogError(ex, $"插入第二张高图失败");
+                                            para2.AppendChild(new Run(doc, "[图片加载失败]"));
+                                        }
+                                    }
+                                }
+                            }
+                        }
+                    }
+                }
+
+                startIndex++;
+            }
+
+            //替换书签
+            foreach (var key in bookmarks.Keys)
+            {
+                if (doc.Range.Bookmarks[key] != null)
+                {
+                    Bookmark mark = doc.Range.Bookmarks[key];
+                    mark.Text = bookmarks[key];
+                }
+            }
+
+            //去水印
+            new Aspose.Words.License().SetLicense(new MemoryStream(Convert.FromBase64String(AsposeHelper.asposeKey)));
+
+            //保存word
+            string fileName = $"活动验收报告_{di.TeamName}_{DateTime.Now:yyyyMMddHHmmss}.docx";
+            string filePath = $"InspectionReport/{fileName}";
+            string fullPath = AppSettingsHelper.Get("WordBasePath") + filePath;
+
+            //确保目录存在
+            string directory = Path.GetDirectoryName(fullPath);
+            if (!Directory.Exists(directory))
+            {
+                Directory.CreateDirectory(directory);
+            }
+
+            //保存文档
+            doc.Save(fullPath, Aspose.Words.SaveFormat.Docx);
+
+            //返回文件路径http
+            string url = AppSettingsHelper.Get("WordBaseUrl") + $"Office/Word/{filePath}";
+
+            return Ok(JsonView(true, "SUCCESS!", new { Url = url, FileName = fileName }));
+        }
 
 
 

+ 5 - 0
OASystem/OASystem.Domain/Dtos/Groups/ConferenceAffairsInIt.cs

@@ -27,6 +27,11 @@ namespace OASystem.Domain.Dtos.Groups
         public List<string> fileNames { get; set; }
     }
 
+    public class InspectionReportFileDownDto
+    {
+        public int Diid { get; set; }
+    }
+
     public class ConferenceAffairsSaveDto
     {
         /// <summary>