diff --git a/Infrastructure/Helper/ExcelHelper.cs b/Infrastructure/Helper/ExcelHelper.cs new file mode 100644 index 0000000..6e17d32 --- /dev/null +++ b/Infrastructure/Helper/ExcelHelper.cs @@ -0,0 +1,78 @@ +using Microsoft.AspNetCore.Hosting; + +using OfficeOpenXml; + +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace ZR.Infrastructure.Helper +{ + /// + /// Excel 导出帮助类(EPPlus) + /// + public class ExcelHelper + { + private readonly IWebHostEnvironment _webHostEnvironment; + + /// + /// 构造函数,需要注入 IWebHostEnvironment 获取 web 根目录 + /// + /// + public ExcelHelper(IWebHostEnvironment webHostEnvironment) + { + _webHostEnvironment = webHostEnvironment; + ExcelPackage.License.SetNonCommercialPersonal("pnaa"); + + } + + /// + /// 导出 Excel 文件 + /// + /// 数据类型 + /// 数据列表 + /// Sheet 名 + /// 文件名,不含时间戳和后缀 + /// 返回文件名和完整路径 + public (string, string) ExportExcel(List list, string sheetName, string fileName) + { + // 生成带时间戳的文件名 + string sFileName = $"{fileName}_{DateTime.Now:MMdd_HHmmss}.xlsx"; + string fullPath = Path.Combine(_webHostEnvironment.WebRootPath, "export", sFileName); + + // 创建目录 + Directory.CreateDirectory(Path.GetDirectoryName(fullPath)); + + using (var package = new ExcelPackage()) + { + + // 添加 Sheet + var worksheet = package.Workbook.Worksheets.Add(sheetName ?? "Sheet1"); + + // 将 List 导入到 Sheet + worksheet.Cells["A2"].LoadFromCollection(list, false); // true 表示包含表头 + // 插入图片 + + var pic = worksheet.Drawings.AddPicture("Logo", new FileInfo("D:\\CodeManage\\Zr.Admin.NET\\ZR.Admin.WebApi\\wwwroot\\workfiles\\2025\\20250818\\当日照片\\1755531044_7059.jpg")); + // 设置图片位置 + pic.SetPosition(4, 0, 4, 0); // 行, 行偏移, 列, 列偏移 + pic.SetSize(100, 50); // 宽高像素 + // 自动调整列宽 + worksheet.Cells[worksheet.Dimension.Address].AutoFitColumns(); + + // 保存文件 + package.SaveAs(new FileInfo(fullPath)); + } + + return (sFileName, fullPath); + } + + + + + + } +} diff --git a/Infrastructure/ZR.Infrastructure.csproj b/Infrastructure/ZR.Infrastructure.csproj index 998f38e..4d9e0a9 100644 --- a/Infrastructure/ZR.Infrastructure.csproj +++ b/Infrastructure/ZR.Infrastructure.csproj @@ -12,6 +12,7 @@ + diff --git a/ZR.Admin.WebApi/Controllers/Business/CamWorkersController.cs b/ZR.Admin.WebApi/Controllers/Business/CamWorkersController.cs new file mode 100644 index 0000000..ba80909 --- /dev/null +++ b/ZR.Admin.WebApi/Controllers/Business/CamWorkersController.cs @@ -0,0 +1,73 @@ +using Microsoft.AspNetCore.Mvc; +using ZR.Model.Business.Dto; +using ZR.Model.Business; +using ZR.Service.Business.IBusinessService; + +//创建时间:2025-08-19 +namespace ZR.Admin.WebApi.Controllers.Business +{ + /// + /// 月报表 + /// + [Route("business/CamWorkers")] + public class CamWorkersController : BaseController + { + /// + /// 月报表接口 + /// + private readonly ICamWorkersService _CamWorkersService; + + public CamWorkersController(ICamWorkersService CamWorkersService) + { + _CamWorkersService = CamWorkersService; + } + + /// + /// 查询月报表列表 + /// + /// + /// + [HttpGet("list")] + [ActionPermissionFilter(Permission = "camworkers:list")] + public IActionResult QueryCamWorkers([FromQuery] CamWorkersQueryDto parm) + { + var response = _CamWorkersService.GetList(parm); + return SUCCESS(response); + } + + + /// + /// 查询月报表详情 + /// + /// + /// + [HttpGet("{Id}")] + [ActionPermissionFilter(Permission = "camworkers:query")] + public IActionResult GetCamWorkers(long Id) + { + var response = _CamWorkersService.GetInfo(Id); + + var info = response.Adapt(); + return SUCCESS(info); + } + + /// + /// 导出月报表 + /// + /// + [Log(Title = "月报表", BusinessType = BusinessType.EXPORT, IsSaveResponseData = false)] + [HttpGet("export")] + [ActionPermissionFilter(Permission = "camworkers:export")] + public IActionResult Export([FromQuery] CamWorkersQueryDto parm) + { + var list = _CamWorkersService.ExportList(parm); + if (list == null || list.Count <= 0) + { + return ToResponse(ResultCode.FAIL, "没有要导出的数据"); + } + var result = ExportExcelMini(list, "月报表", "月报表"); + return ExportExcel(result.Item2, result.Item1); + } + + } +} \ No newline at end of file diff --git a/ZR.Admin.WebApi/Controllers/Business/CamWorkrecordController.cs b/ZR.Admin.WebApi/Controllers/Business/CamWorkrecordController.cs index 165e25a..88e3dff 100644 --- a/ZR.Admin.WebApi/Controllers/Business/CamWorkrecordController.cs +++ b/ZR.Admin.WebApi/Controllers/Business/CamWorkrecordController.cs @@ -2,7 +2,21 @@ using Microsoft.AspNetCore.Mvc; using ZR.Model.Business.Dto; using ZR.Model.Business; using ZR.Service.Business.IBusinessService; - +using MiniExcelLibs.Picture; +using SKIT.FlurlHttpClient.Wechat.Api.Models; +using Microsoft.Extensions.Options; +using Microsoft.AspNetCore.Hosting; +using MiniExcelLibs; +using System.IO; +using IOFile = System.IO.File; +using Org.BouncyCastle.Utilities; +using Microsoft.Extensions.Configuration.UserSecrets; +using MiniExcelLibs.OpenXml; +using SixLabors.ImageSharp; +using SixLabors.ImageSharp.Formats.Jpeg; +using ZR.Infrastructure.Helper; +using OfficeOpenXml; +using OfficeOpenXml.Drawing; //创建时间:2025-08-18 namespace ZR.Admin.WebApi.Controllers.Business { @@ -17,9 +31,15 @@ namespace ZR.Admin.WebApi.Controllers.Business /// private readonly ICamWorkrecordService _CamWorkrecordService; - public CamWorkrecordController(ICamWorkrecordService CamWorkrecordService) + private OptionsSetting OptionsSetting; + private IWebHostEnvironment WebHostEnvironment; + + + public CamWorkrecordController(ICamWorkrecordService CamWorkrecordService, IOptions options, IWebHostEnvironment webHostEnvironment) { _CamWorkrecordService = CamWorkrecordService; + OptionsSetting = options.Value; + WebHostEnvironment = webHostEnvironment; } /// @@ -46,7 +66,7 @@ namespace ZR.Admin.WebApi.Controllers.Business public IActionResult GetCamWorkrecord(int Id) { var response = _CamWorkrecordService.GetInfo(Id); - + var info = response.Adapt(); return SUCCESS(info); } @@ -89,12 +109,155 @@ namespace ZR.Admin.WebApi.Controllers.Business [HttpPost("delete/{ids}")] [ActionPermissionFilter(Permission = "camworkrecord:delete")] [Log(Title = "工作记录", BusinessType = BusinessType.DELETE)] - public IActionResult DeleteCamWorkrecord([FromRoute]string ids) + public IActionResult DeleteCamWorkrecord([FromRoute] string ids) { var idArr = Tools.SplitAndConvert(ids); return ToResponse(_CamWorkrecordService.Delete(idArr, "删除工作记录")); } + /// + /// 导出工作记录 + /// + /// + [Log(Title = "工作记录", BusinessType = BusinessType.EXPORT, IsSaveResponseData = false)] + [HttpGet("export")] + [ActionPermissionFilter(Permission = "camworkrecord:export")] + public IActionResult Export([FromQuery] CamWorkrecordQueryDto parm) + { + var list = _CamWorkrecordService.ExportList(parm).Result; + if (list == null || list.Count <= 0) + { + return ToResponse(ResultCode.FAIL, "没有要导出的数据"); + } + var url = OptionsSetting.Upload.UploadUrl; + string savePath = Path.Combine(WebHostEnvironment.WebRootPath); + int i = 1; + list.ForEach(it => + { + var temp = string.IsNullOrEmpty(it.ImageUrl) ? "" : it.ImageUrl; + if (temp.IndexOf("http") > -1) + { + var image = temp.Replace(url, ""); + temp = savePath + image; + } + it.Index = i; + it.ImageUrl = temp; + //it.Image = CompressImage(temp, 50); + i++; + }); + ExcelHelper excelHelper = new ExcelHelper(WebHostEnvironment); + ExcelPackage.License.SetNonCommercialPersonal("pnaa"); + var result = ExportWorkRecordExcel(list, "工作记录", 200, 70,60); + //ExportExcelMini(list, "工作记录", "工作记录"); + //ExportExcelWithImagesInBatches(result.Item2, "工作记录", urlList, 10); + //loadExcel(); + return ExportExcel(result.Item2, result.Item1); + } + + /// + public (string fileName, string fullPath) ExportWorkRecordExcel(List list, string fileName, int imageWidth = 100, int imageHeight = 60, int imageQuality = 50) + { + IWebHostEnvironment webHostEnvironment = (IWebHostEnvironment)App.ServiceProvider.GetService(typeof(IWebHostEnvironment)); + string sFileName = $"{fileName}_{DateTime.Now:yyyyMMdd_HHmmss}.xlsx"; + string fullPath = Path.Combine(webHostEnvironment.WebRootPath, "export", sFileName); + Directory.CreateDirectory(Path.GetDirectoryName(fullPath)); + + using var package = new ExcelPackage(); + + var ws = package.Workbook.Worksheets.Add("工作记录"); + + // 写表头 + var headers = new[] + { + "序号","部门名称","拍照时间","经度","纬度","位置","工作内容","施工人员","状态","施工图片","创建时间","更新时间" + }; + for (int i = 0; i < headers.Length; i++) + { + ws.Cells[1, i + 1].Value = headers[i]; + ws.Cells[1, i + 1].Style.Font.Bold = true; + //ws.Column(i).Width = 120; + } + + //ws.Column(10).Width = 40; + + int row = 2; + foreach (var item in list) + { + ws.Cells[row, 1].Value = item.Index; + ws.Cells[row, 2].Value = item.DeptName; + ws.Cells[row, 3].Value = item.RecordTime?.ToString("yyyy-MM-dd HH:mm:ss"); + ws.Cells[row, 4].Value = item.Longitude; + ws.Cells[row, 5].Value = item.Latitude; + ws.Cells[row, 6].Value = item.Address; + ws.Cells[row, 7].Value = item.Content; + ws.Cells[row, 8].Value = item.Worker; + ws.Cells[row, 9].Value = item.StatusName; + ws.Cells[row, 11].Value = item.CreateTime?.ToString("yyyy-MM-dd HH:mm:ss"); + ws.Cells[row, 12].Value = item.UpdateTime?.ToString("yyyy-MM-dd HH:mm:ss"); + + // 如果 ImageUrl 有值,则压缩后插入 Excel + if (!string.IsNullOrEmpty(item.ImageUrl) && IOFile.Exists(item.ImageUrl)) + { + using var image = SixLabors.ImageSharp.Image.Load(item.ImageUrl); + var encoder = new JpegEncoder { Quality = imageQuality }; + using var ms = new MemoryStream(); + image.Save(ms, encoder); + ms.Position = 0; + + var pic = ws.Drawings.AddPicture($"Pic_{row}_10", ms); + pic.SetPosition(row - 1, 5, 9, 5); // 第10列 + pic.SetSize(imageWidth, imageHeight); + } + ws.Row(row).Height = imageHeight; + row++; + } + + ws.Cells[ws.Dimension.Address].AutoFitColumns(); + ws.Cells[ws.Dimension.Address].Style.VerticalAlignment = OfficeOpenXml.Style.ExcelVerticalAlignment.Center; + ws.Column(10).Width = 40; + package.SaveAs(new FileInfo(fullPath)); + + return (sFileName, fullPath); + } + + + + + + + public byte[] CompressImage(string imagePath, int quality) + { + // 使用 using 语句确保资源被释放 + using (var image = Image.Load(imagePath)) + { + var encoder = new JpegEncoder { Quality = quality }; + + using (var outputStream = new MemoryStream()) + { + image.Save(outputStream, encoder); + return outputStream.ToArray(); + } + } + } + + + /// + /// 根据图片文件扩展名映射为 ContentType,避免类型不匹配导致 Excel 修复。 + /// + private static string GetContentTypeByExtension(string filePath) + { + var ext = Path.GetExtension(filePath)?.ToLowerInvariant(); + return ext switch + { + ".png" => "image/png", + ".jpg" => "image/jpeg", + ".jpeg" => "image/jpeg", + ".gif" => "image/gif", + ".bmp" => "image/bmp", + ".webp" => "image/webp", // 只有新版本 Excel 兼容,谨慎使用 + _ => "image/png" // 默认按 png 处理 + }; + } } } \ No newline at end of file diff --git a/ZR.Admin.WebApi/Controllers/CommonController.cs b/ZR.Admin.WebApi/Controllers/CommonController.cs index 1d8be58..1efb907 100644 --- a/ZR.Admin.WebApi/Controllers/CommonController.cs +++ b/ZR.Admin.WebApi/Controllers/CommonController.cs @@ -15,7 +15,11 @@ using ZR.Service.Business.IBusinessService; using ZR.Service.Business; using System.Threading.Tasks; using static SKIT.FlurlHttpClient.Wechat.Api.Models.CgibinExpressIntracityUpdateStoreRequest.Types; - +using Aliyun.OSS.Model; +using System.IO.Compression; +using IOFile = System.IO.File; +using SixLabors.ImageSharp.Formats.Jpeg; +using SixLabors.ImageSharp; namespace ZR.Admin.WebApi.Controllers { /// @@ -34,7 +38,6 @@ namespace ZR.Admin.WebApi.Controllers public readonly ISysDeptService _deptService; public readonly ISysDictDataService sysDictDataService; - private string domainUrl = AppSettings.GetConfig("Upload:uploadUrl"); /// /// 工作记录接口 /// @@ -272,8 +275,8 @@ namespace ZR.Admin.WebApi.Controllers //- 当日根据【工作内容】分类的照片 //- 当日根据【部门】分类的照片 var imageprx = ImageConverter.GetFileExtensionFromBase64(parm.Image); - var imageName = ImageConverter.GenerateImageFileName(imageprx); - var filePath = "/workfiles/" + DateTime.Now.ToString("yyyy/yyyyMMdd"); + + var filePath = "/workfiles/" + DateTime.Now.ToString("yyyyMM/yyyyMMdd"); string savePath = Path.Combine(WebHostEnvironment.WebRootPath); var path = savePath + filePath; var images = ImageConverter.Base64ToImageBytes(parm.Image); @@ -281,6 +284,14 @@ namespace ZR.Admin.WebApi.Controllers { return ToResponse(ResultCode.CUSTOM_ERROR, "图片上传失败"); } + int MaxSize = 300 * 1024; // 300KB = 307200 字节 + // 如果图片大于300KB才压缩 + if (images.Length > MaxSize) + { + images = CompressImage(images, 70); // 压缩质量 70 + imageprx = ".jpg"; + } + var imageName = ImageConverter.GenerateImageFileName(imageprx); var participantsUrl = $"{path}/参与人员/"; var photosDay = $"{path}/当日照片/"; var jobContent = $"{path}/工作内容/"; @@ -331,6 +342,7 @@ namespace ZR.Admin.WebApi.Controllers { await stream.WriteAsync(images, 0, images.Length); } + var domainUrl = $"{OptionsSetting.Upload.UploadUrl}"; //备份一下本地 var modal = parm.Adapt().ToCreate(HttpContext); modal.CreateTime = DateTime.Now; @@ -353,5 +365,54 @@ namespace ZR.Admin.WebApi.Controllers _CamWorkerService.AsInsertable(workers).ExecuteCommand(); return SUCCESS(1); } + + [HttpGet] + [Route("/getDownloadZip")] + [AllowAnonymous] + public async Task DownloadZip([FromQuery] string? yearMoney) + { + if (string.IsNullOrEmpty(yearMoney)) + { + yearMoney = DateTime.Now.ToString("yyyyMM"); + } + if (yearMoney.IndexOf("-") > -1) + { + yearMoney = yearMoney.Replace("-", ""); + } + var filePath = "/workfiles/" + yearMoney; + string savePath = Path.Combine(WebHostEnvironment.WebRootPath); + var path = savePath + filePath; + if (!Directory.Exists(path)) + { + return ToResponse(ResultCode.FAIL, "无数据"); + } + var outputPath = WebHostEnvironment.WebRootPath + "/workfiles/temp/"; + if (!Directory.Exists(outputPath)) + { + Directory.CreateDirectory(outputPath); + } + var zipReturnFileName = $"{outputPath}{yearMoney}.zip"; + if (IOFile.Exists(zipReturnFileName)) + { + IOFile.Delete(zipReturnFileName); + } + ZipFile.CreateFromDirectory(path, zipReturnFileName); + return DownFile(zipReturnFileName, $"{yearMoney}.zip"); + } + + public byte[] CompressImage(byte[] imageBytes, int quality) + { + using (var inputStream = new MemoryStream(imageBytes)) + using (var image = Image.Load(inputStream)) + { + var encoder = new JpegEncoder { Quality = quality }; + + using (var outputStream = new MemoryStream()) + { + image.Save(outputStream, encoder); + return outputStream.ToArray(); + } + } + } } } diff --git a/ZR.Admin.WebApi/ZR.Admin.WebApi.csproj b/ZR.Admin.WebApi/ZR.Admin.WebApi.csproj index 140ad7d..02a1cf9 100644 --- a/ZR.Admin.WebApi/ZR.Admin.WebApi.csproj +++ b/ZR.Admin.WebApi/ZR.Admin.WebApi.csproj @@ -45,6 +45,7 @@ + diff --git a/ZR.Admin.WebApi/wwwroot/workfiles/2025/20250818/参与人员/张三/1755531373_7849.jpg b/ZR.Admin.WebApi/wwwroot/workfiles/2025/20250818/参与人员/张三/1755531373_7849.jpg deleted file mode 100644 index 9a41ca5..0000000 Binary files a/ZR.Admin.WebApi/wwwroot/workfiles/2025/20250818/参与人员/张三/1755531373_7849.jpg and /dev/null differ diff --git a/ZR.Admin.WebApi/wwwroot/workfiles/2025/20250818/参与人员/李四/1755531373_7849.jpg b/ZR.Admin.WebApi/wwwroot/workfiles/2025/20250818/参与人员/李四/1755531373_7849.jpg deleted file mode 100644 index 9a41ca5..0000000 Binary files a/ZR.Admin.WebApi/wwwroot/workfiles/2025/20250818/参与人员/李四/1755531373_7849.jpg and /dev/null differ diff --git a/ZR.Admin.WebApi/wwwroot/workfiles/2025/20250818/参与人员/脾气/1755531044_7059.jpg b/ZR.Admin.WebApi/wwwroot/workfiles/2025/20250818/参与人员/脾气/1755531044_7059.jpg deleted file mode 100644 index 63f2785..0000000 Binary files a/ZR.Admin.WebApi/wwwroot/workfiles/2025/20250818/参与人员/脾气/1755531044_7059.jpg and /dev/null differ diff --git a/ZR.Admin.WebApi/wwwroot/workfiles/2025/20250818/工作内容/泡三/1755531044_7059.jpg b/ZR.Admin.WebApi/wwwroot/workfiles/2025/20250818/工作内容/泡三/1755531044_7059.jpg deleted file mode 100644 index 63f2785..0000000 Binary files a/ZR.Admin.WebApi/wwwroot/workfiles/2025/20250818/工作内容/泡三/1755531044_7059.jpg and /dev/null differ diff --git a/ZR.Admin.WebApi/wwwroot/workfiles/2025/20250818/工作内容/测试1/1755531373_7849.jpg b/ZR.Admin.WebApi/wwwroot/workfiles/2025/20250818/工作内容/测试1/1755531373_7849.jpg deleted file mode 100644 index 9a41ca5..0000000 Binary files a/ZR.Admin.WebApi/wwwroot/workfiles/2025/20250818/工作内容/测试1/1755531373_7849.jpg and /dev/null differ diff --git a/ZR.Admin.WebApi/wwwroot/workfiles/2025/20250818/当日照片/1755531044_7059.jpg b/ZR.Admin.WebApi/wwwroot/workfiles/2025/20250818/当日照片/1755531044_7059.jpg deleted file mode 100644 index 63f2785..0000000 Binary files a/ZR.Admin.WebApi/wwwroot/workfiles/2025/20250818/当日照片/1755531044_7059.jpg and /dev/null differ diff --git a/ZR.Admin.WebApi/wwwroot/workfiles/2025/20250818/当日照片/1755531373_7849.jpg b/ZR.Admin.WebApi/wwwroot/workfiles/2025/20250818/当日照片/1755531373_7849.jpg deleted file mode 100644 index 9a41ca5..0000000 Binary files a/ZR.Admin.WebApi/wwwroot/workfiles/2025/20250818/当日照片/1755531373_7849.jpg and /dev/null differ diff --git a/ZR.Admin.WebApi/wwwroot/workfiles/2025/20250818/部门/研发部门/1755531044_7059.jpg b/ZR.Admin.WebApi/wwwroot/workfiles/2025/20250818/部门/研发部门/1755531044_7059.jpg deleted file mode 100644 index 63f2785..0000000 Binary files a/ZR.Admin.WebApi/wwwroot/workfiles/2025/20250818/部门/研发部门/1755531044_7059.jpg and /dev/null differ diff --git a/ZR.Admin.WebApi/wwwroot/workfiles/2025/20250818/部门/研发部门/1755531373_7849.jpg b/ZR.Admin.WebApi/wwwroot/workfiles/2025/20250818/部门/研发部门/1755531373_7849.jpg deleted file mode 100644 index 9a41ca5..0000000 Binary files a/ZR.Admin.WebApi/wwwroot/workfiles/2025/20250818/部门/研发部门/1755531373_7849.jpg and /dev/null differ diff --git a/ZR.Admin.WebApi/wwwroot/workfiles/202508/20250819/参与人员/张三/1755617080_7078.jpg b/ZR.Admin.WebApi/wwwroot/workfiles/202508/20250819/参与人员/张三/1755617080_7078.jpg new file mode 100644 index 0000000..593533f Binary files /dev/null and b/ZR.Admin.WebApi/wwwroot/workfiles/202508/20250819/参与人员/张三/1755617080_7078.jpg differ diff --git a/ZR.Admin.WebApi/wwwroot/workfiles/202508/20250819/参与人员/张三/1755617093_1631.jpg b/ZR.Admin.WebApi/wwwroot/workfiles/202508/20250819/参与人员/张三/1755617093_1631.jpg new file mode 100644 index 0000000..e4a74ed Binary files /dev/null and b/ZR.Admin.WebApi/wwwroot/workfiles/202508/20250819/参与人员/张三/1755617093_1631.jpg differ diff --git a/ZR.Admin.WebApi/wwwroot/workfiles/202508/20250819/参与人员/李四/1755617080_7078.jpg b/ZR.Admin.WebApi/wwwroot/workfiles/202508/20250819/参与人员/李四/1755617080_7078.jpg new file mode 100644 index 0000000..593533f Binary files /dev/null and b/ZR.Admin.WebApi/wwwroot/workfiles/202508/20250819/参与人员/李四/1755617080_7078.jpg differ diff --git a/ZR.Admin.WebApi/wwwroot/workfiles/202508/20250819/参与人员/李四/1755617093_1631.jpg b/ZR.Admin.WebApi/wwwroot/workfiles/202508/20250819/参与人员/李四/1755617093_1631.jpg new file mode 100644 index 0000000..e4a74ed Binary files /dev/null and b/ZR.Admin.WebApi/wwwroot/workfiles/202508/20250819/参与人员/李四/1755617093_1631.jpg differ diff --git a/ZR.Admin.WebApi/wwwroot/workfiles/202508/20250819/参与人员/王五/1755617080_7078.jpg b/ZR.Admin.WebApi/wwwroot/workfiles/202508/20250819/参与人员/王五/1755617080_7078.jpg new file mode 100644 index 0000000..593533f Binary files /dev/null and b/ZR.Admin.WebApi/wwwroot/workfiles/202508/20250819/参与人员/王五/1755617080_7078.jpg differ diff --git a/ZR.Admin.WebApi/wwwroot/workfiles/202508/20250819/参与人员/王五/1755617093_1631.jpg b/ZR.Admin.WebApi/wwwroot/workfiles/202508/20250819/参与人员/王五/1755617093_1631.jpg new file mode 100644 index 0000000..e4a74ed Binary files /dev/null and b/ZR.Admin.WebApi/wwwroot/workfiles/202508/20250819/参与人员/王五/1755617093_1631.jpg differ diff --git a/ZR.Admin.WebApi/wwwroot/workfiles/202508/20250819/工作内容/测试/1755617080_7078.jpg b/ZR.Admin.WebApi/wwwroot/workfiles/202508/20250819/工作内容/测试/1755617080_7078.jpg new file mode 100644 index 0000000..593533f Binary files /dev/null and b/ZR.Admin.WebApi/wwwroot/workfiles/202508/20250819/工作内容/测试/1755617080_7078.jpg differ diff --git a/ZR.Admin.WebApi/wwwroot/workfiles/202508/20250819/工作内容/测试/1755617093_1631.jpg b/ZR.Admin.WebApi/wwwroot/workfiles/202508/20250819/工作内容/测试/1755617093_1631.jpg new file mode 100644 index 0000000..e4a74ed Binary files /dev/null and b/ZR.Admin.WebApi/wwwroot/workfiles/202508/20250819/工作内容/测试/1755617093_1631.jpg differ diff --git a/ZR.Admin.WebApi/wwwroot/workfiles/202508/20250819/当日照片/1755617080_7078.jpg b/ZR.Admin.WebApi/wwwroot/workfiles/202508/20250819/当日照片/1755617080_7078.jpg new file mode 100644 index 0000000..593533f Binary files /dev/null and b/ZR.Admin.WebApi/wwwroot/workfiles/202508/20250819/当日照片/1755617080_7078.jpg differ diff --git a/ZR.Admin.WebApi/wwwroot/workfiles/202508/20250819/当日照片/1755617093_1631.jpg b/ZR.Admin.WebApi/wwwroot/workfiles/202508/20250819/当日照片/1755617093_1631.jpg new file mode 100644 index 0000000..e4a74ed Binary files /dev/null and b/ZR.Admin.WebApi/wwwroot/workfiles/202508/20250819/当日照片/1755617093_1631.jpg differ diff --git a/ZR.Admin.WebApi/wwwroot/workfiles/202508/20250819/部门/研发部门/1755617080_7078.jpg b/ZR.Admin.WebApi/wwwroot/workfiles/202508/20250819/部门/研发部门/1755617080_7078.jpg new file mode 100644 index 0000000..593533f Binary files /dev/null and b/ZR.Admin.WebApi/wwwroot/workfiles/202508/20250819/部门/研发部门/1755617080_7078.jpg differ diff --git a/ZR.Admin.WebApi/wwwroot/workfiles/202508/20250819/部门/研发部门/1755617093_1631.jpg b/ZR.Admin.WebApi/wwwroot/workfiles/202508/20250819/部门/研发部门/1755617093_1631.jpg new file mode 100644 index 0000000..e4a74ed Binary files /dev/null and b/ZR.Admin.WebApi/wwwroot/workfiles/202508/20250819/部门/研发部门/1755617093_1631.jpg differ diff --git a/ZR.Admin.WebApi/wwwroot/workfiles/temp/202508.zip b/ZR.Admin.WebApi/wwwroot/workfiles/temp/202508.zip new file mode 100644 index 0000000..ec6e891 Binary files /dev/null and b/ZR.Admin.WebApi/wwwroot/workfiles/temp/202508.zip differ diff --git a/ZR.Model/Business/CamWorkers.cs b/ZR.Model/Business/CamWorkers.cs new file mode 100644 index 0000000..b170b3c --- /dev/null +++ b/ZR.Model/Business/CamWorkers.cs @@ -0,0 +1,37 @@ + +namespace ZR.Model.Business +{ + /// + /// 月报表 + /// + [SugarTable("cam_workers")] + public class CamWorkers + { + /// + /// Id + /// + [SugarColumn(IsPrimaryKey = true, IsIdentity = true)] + public long Id { get; set; } + + /// + /// WorkrecordId + /// + public int WorkrecordId { get; set; } + + /// + /// WorkerName + /// + public string WorkerName { get; set; } + + /// + /// WorkerDay + /// + public int WorkerDay { get; set; } + + /// + /// CreateTime + /// + public DateTime? CreateTime { get; set; } + + } +} \ No newline at end of file diff --git a/ZR.Model/Business/Dto/CamWorkerDto.cs b/ZR.Model/Business/Dto/CamWorkerDto.cs index 31cde2c..bf995c0 100644 --- a/ZR.Model/Business/Dto/CamWorkerDto.cs +++ b/ZR.Model/Business/Dto/CamWorkerDto.cs @@ -4,7 +4,7 @@ namespace ZR.Model.Business.Dto /// /// 工作人员记录查询对象 /// - public class CamWorkerQueryDto : PagerInfo + public class CamWorkerQueryDto : PagerInfo { } @@ -28,5 +28,22 @@ namespace ZR.Model.Business.Dto + } + + + /// + /// 工作人员记录输入输出对象 + /// + public class CamWorkersDto + { + [Required(ErrorMessage = "主键不能为空")] + public long Id { get; set; } + + + + [Required(ErrorMessage = "人员不能为空")] + public string WorkerName { get; set; } + + } } \ No newline at end of file diff --git a/ZR.Model/Business/Dto/CamWorkersDto.cs b/ZR.Model/Business/Dto/CamWorkersDto.cs new file mode 100644 index 0000000..7c20ba8 --- /dev/null +++ b/ZR.Model/Business/Dto/CamWorkersDto.cs @@ -0,0 +1,81 @@ + +namespace ZR.Model.Business.Dto +{ + /// + /// 月报表查询对象 + /// + public class CamWorkersQueryDto + { + public string WorkerName { get; set; } + public string YearMonth { get; set; } + } + + /// + /// 月报表输入输出对象 + /// + public class CamWorkersfDto + { + [Required(ErrorMessage = "Id不能为空")] + [ExcelColumn(Name = "Id")] + [ExcelColumnName("Id")] + public long Id { get; set; } + + [Required(ErrorMessage = "WorkrecordId不能为空")] + [ExcelColumn(Name = "WorkrecordId")] + [ExcelColumnName("WorkrecordId")] + public int WorkrecordId { get; set; } + + [Required(ErrorMessage = "WorkerName不能为空")] + [ExcelColumn(Name = "WorkerName")] + [ExcelColumnName("WorkerName")] + public string WorkerName { get; set; } + + [Required(ErrorMessage = "WorkerDay不能为空")] + [ExcelColumn(Name = "WorkerDay")] + [ExcelColumnName("WorkerDay")] + public int WorkerDay { get; set; } + + [Required(ErrorMessage = "CreateTime不能为空")] + [ExcelColumn(Name = "CreateTime", Format = "yyyy-MM-dd HH:mm:ss", Width = 20)] + [ExcelColumnName("CreateTime")] + public DateTime? CreateTime { get; set; } + + + + } + + /// + /// 每月员工工作天数统计结果 + /// + public class WorkerMonthlyWorkDays + { + /// + /// 年月(格式:yyyy-MM) + /// + [ExcelColumn(Name = "月份")] + [ExcelColumnName("月份")] + public string YearMonth { get; set; } + + /// + /// 部门名称 + /// + [ExcelColumn(Name = "部门名称")] + [ExcelColumnName("部门名称")] + public string DeptName { get; set; } + + /// + /// 员工姓名 + /// + [ExcelColumn(Name = "员工姓名")] + [ExcelColumnName("员工姓名")] + public string WorkerName { get; set; } + + /// + /// 当月工作天数 + /// + [ExcelColumn(Name = "当月工作天数")] + [ExcelColumnName("当月工作天数")] + public int WorkDays { get; set; } + } + +} \ No newline at end of file diff --git a/ZR.Model/Business/Dto/CamWorkrecordDto.cs b/ZR.Model/Business/Dto/CamWorkrecordDto.cs index fefca1c..6821cf4 100644 --- a/ZR.Model/Business/Dto/CamWorkrecordDto.cs +++ b/ZR.Model/Business/Dto/CamWorkrecordDto.cs @@ -10,6 +10,8 @@ namespace ZR.Model.Business.Dto public string Address { get; set; } public string Content { get; set; } public string StatusName { get; set; } + public DateTime? BeginRecordTime { get; set; } + public DateTime? EndRecordTime { get; set; } } /// @@ -42,7 +44,17 @@ namespace ZR.Model.Business.Dto public DateTime? UpdateTime { get; set; } + public Dictionary RemarksDic { get; set; } + /// + /// 施工人员 + /// + public List Workers { get; set; } + + /// + /// 施工人员 + /// + public string Worker { get; set; } [ExcelColumn(Name = "状态")] public string StatusNameLabel { get; set; } @@ -103,4 +115,82 @@ namespace ZR.Model.Business.Dto /// public List Workers { get; set; } } + + /// + /// 工作记录输入输出对象 + /// + public class CamWorkrecordExcelDto + { + [ExcelIgnore] + public int Id { get; set; } + + + [ExcelColumn(Name = "序号")] + [ExcelColumnName("序号")] + public int Index { get; set; } + + [ExcelColumn(Name = "部门名称")] + [ExcelColumnName("部门名称")] + public string DeptName { get; set; } + + [ExcelColumn(Name = "拍照时间", Format = "yyyy-MM-dd HH:mm:ss", Width = 20)] + [ExcelColumnName("拍照时间")] + public DateTime? RecordTime { get; set; } + + [ExcelColumn(Name = "经度")] + [ExcelColumnName("经度")] + public string Longitude { get; set; } + + [ExcelColumn(Name = "纬度")] + [ExcelColumnName("纬度")] + public string Latitude { get; set; } + + [ExcelColumn(Name = "位置")] + [ExcelColumnName("位置")] + public string Address { get; set; } + + [ExcelColumn(Name = "工作内容")] + [ExcelColumnName("工作内容")] + public string Content { get; set; } + + /// + /// + /// + [ExcelIgnore] + public List Workers { get; set; } + + [ExcelColumn(Name = "施工人员")] + [ExcelColumnName("施工人员")] + public string Worker + { + get + { + return Workers != null ? string.Join(",", Workers) : string.Empty; + } + } + [ExcelColumn(Name = "状态")] + [ExcelColumnName("状态")] + public string StatusName { get; set; } + + [ExcelIgnore] + public string Remarks { get; set; } + + [ExcelColumn(Name = "施工图片", Width = 100)] + [ExcelColumnName("施工图片")] + public byte[] Image { get; set; } + + [ExcelColumn(Name = "创建时间", Format = "yyyy-MM-dd HH:mm:ss", Width = 20)] + [ExcelColumnName("创建时间")] + public DateTime? CreateTime { get; set; } + + [ExcelColumn(Name = "更新时间", Format = "yyyy-MM-dd HH:mm:ss", Width = 20)] + [ExcelColumnName("更新时间")] + public DateTime? UpdateTime { get; set; } + + [ExcelIgnore] + public string ImageUrl { get; set; } + + + } + } \ No newline at end of file diff --git a/ZR.Service/Business/CamWorkersService.cs b/ZR.Service/Business/CamWorkersService.cs new file mode 100644 index 0000000..ade35e0 --- /dev/null +++ b/ZR.Service/Business/CamWorkersService.cs @@ -0,0 +1,115 @@ +using Infrastructure.Attribute; +using Infrastructure.Extensions; +using ZR.Model.Business.Dto; +using ZR.Model.Business; +using ZR.Repository; +using ZR.Service.Business.IBusinessService; + +namespace ZR.Service.Business +{ + /// + /// 月报表Service业务层处理 + /// + [AppService(ServiceType = typeof(ICamWorkersService), ServiceLifetime = LifeTime.Transient)] + public class CamWorkersService : BaseService, ICamWorkersService + { + private readonly ICamWorkrecordService _camWorkrecordService; + private readonly ICamWorkerService _camWorkerService; + public CamWorkersService(ICamWorkrecordService camWorkrecordService, ICamWorkerService camWorkerService) + { + + + _camWorkrecordService = camWorkrecordService; + _camWorkerService = camWorkerService; + } + /// + /// 查询月报表列表 + /// + /// + /// + public List GetList(CamWorkersQueryDto parm) + { + string where = ""; + if (!string.IsNullOrEmpty(parm.WorkerName)) + { + where += $" and w.WorkerName like '%{parm.WorkerName}%'"; + } + if (parm.YearMonth != null) + { + where += $" and CONVERT(varchar(7), CAST(r.RecordTime AS date), 120) = '{parm.YearMonth}'"; + } + var predicate = QueryExp(parm); + var list = Context.Ado.SqlQuery($@" +SELECT + r.DeptName, + w.WorkerName, + CONVERT(varchar(7), CAST(r.RecordTime AS date), 120) AS YearMonth, + COUNT(DISTINCT CAST(r.RecordTime AS date)) AS WorkDays +FROM cam_worker w +LEFT JOIN cam_workrecord r ON w.workrecordId = r.Id where 1=1 {where} +GROUP BY + r.DeptName, + w.WorkerName, + CONVERT(varchar(7), CAST(r.RecordTime AS date), 120) +ORDER BY + r.DeptName, + w.WorkerName, + YearMonth +"); + //.Where(predicate.ToExpression()) + //var response = Queryable() + // //.OrderBy("WorkerName asc") + // .Where(predicate.ToExpression()) + // .ToPage(parm); + + return list; + } + + + /// + /// 获取详情 + /// + /// + /// + public CamWorkers GetInfo(long Id) + { + var response = Queryable() + .Where(x => x.Id == Id) + .First(); + + return response; + } + + /// + /// 添加月报表 + /// + /// + /// + public CamWorkers AddCamWorkers(CamWorkers model) + { + return Insertable(model).ExecuteReturnEntity(); + } + + /// + /// 导出月报表 + /// + /// + /// + public List ExportList(CamWorkersQueryDto parm) + { + return GetList(parm); + } + + /// + /// 查询导出表达式 + /// + /// + /// + private static Expressionable QueryExp(CamWorkersQueryDto parm) + { + var predicate = Expressionable.Create(); + + return predicate; + } + } +} \ No newline at end of file diff --git a/ZR.Service/Business/CamWorkrecordService.cs b/ZR.Service/Business/CamWorkrecordService.cs index f0e26ca..e1a2b5c 100644 --- a/ZR.Service/Business/CamWorkrecordService.cs +++ b/ZR.Service/Business/CamWorkrecordService.cs @@ -4,6 +4,7 @@ using ZR.Model.Business.Dto; using ZR.Model.Business; using ZR.Repository; using ZR.Service.Business.IBusinessService; +using ZR.ServiceCore.Services; namespace ZR.Service.Business { @@ -13,6 +14,13 @@ namespace ZR.Service.Business [AppService(ServiceType = typeof(ICamWorkrecordService), ServiceLifetime = LifeTime.Transient)] public class CamWorkrecordService : BaseService, ICamWorkrecordService { + + private ICamWorkerService camWorkerService; + public CamWorkrecordService(ICamWorkerService camWorkerService) + { + this.camWorkerService = camWorkerService; + } + /// /// 查询工作记录列表 /// @@ -23,10 +31,39 @@ namespace ZR.Service.Business var predicate = QueryExp(parm); var response = Queryable() - //.OrderBy("Id desc") + .OrderBy("Id desc") .Where(predicate.ToExpression()) .ToPage(parm); + var ids = response.Result.Select(it => it.Id).ToList(); + if (ids != null && ids.Count > 0) + { + var works = camWorkerService.AsQueryable().Where(it => ids.Contains(it.WorkrecordId)).ToList(); + response.Result.ForEach(item => + { + var w = works.Where(it => it.WorkrecordId == item.Id).Select(it => new CamWorkersDto { WorkerName = it.WorkerName, Id = it.Id }).ToList(); + item.Workers = w; + if (w.Count > 0) + { + item.Worker = string.Join(",", w.Select(it => it.WorkerName).ToList()); + } + else + { + item.Worker = ""; + } + if (!string.IsNullOrEmpty(item.Remarks)) + { + try + { + item.RemarksDic = JsonConvert.DeserializeObject>(item.Remarks); + } + catch (Exception ex) + { + } + } + }); + + } return response; } @@ -65,6 +102,50 @@ namespace ZR.Service.Business return Update(model, true, "修改工作记录"); } + /// + /// 导出工作记录 + /// + /// + /// + public PagedInfo ExportList(CamWorkrecordQueryDto parm) + { + parm.PageNum = 1; + parm.PageSize = 100000; + var predicate = QueryExp(parm); + + var response = Queryable() + .Where(predicate.ToExpression()) + .Select((it) => new CamWorkrecordExcelDto() + { + + }, true) + .ToPage(parm); + var ids = response.Result.Select(it => it.Id).ToList(); + if (ids != null && ids.Count > 0) + { + var works = camWorkerService.AsQueryable().Where(it => ids.Contains(it.WorkrecordId)).ToList(); + response.Result.ForEach(item => + { + var w = works.Where(it => it.WorkrecordId == item.Id).Select(it => it.WorkerName).ToList(); + item.Workers = w; + + if (!string.IsNullOrEmpty(item.Remarks)) + { + try + { + //item.RemarksDic = JsonConvert.DeserializeObject>(item.Remarks); + } + catch (Exception ex) + { + + } + } + }); + + } + return response; + } + /// /// 查询导出表达式 /// @@ -74,6 +155,9 @@ namespace ZR.Service.Business { var predicate = Expressionable.Create(); + //predicate = predicate.AndIF(parm.BeginRecordTime == null, it => it.RecordTime >= DateTime.Now.ToShortDateString().ParseToDateTime()); + predicate = predicate.AndIF(parm.BeginRecordTime != null, it => it.RecordTime >= parm.BeginRecordTime); + predicate = predicate.AndIF(parm.EndRecordTime != null, it => it.RecordTime <= parm.EndRecordTime); predicate = predicate.AndIF(!string.IsNullOrEmpty(parm.DeptName), it => it.DeptName == parm.DeptName); predicate = predicate.AndIF(!string.IsNullOrEmpty(parm.Address), it => it.Address.Contains(parm.Address)); predicate = predicate.AndIF(!string.IsNullOrEmpty(parm.Content), it => it.Content.Contains(parm.Content)); diff --git a/ZR.Service/Business/IBusinessService/ICamWorkersService.cs b/ZR.Service/Business/IBusinessService/ICamWorkersService.cs new file mode 100644 index 0000000..51f4854 --- /dev/null +++ b/ZR.Service/Business/IBusinessService/ICamWorkersService.cs @@ -0,0 +1,21 @@ +using ZR.Model.Business.Dto; +using ZR.Model.Business; + +namespace ZR.Service.Business.IBusinessService +{ + /// + /// 月报表service接口 + /// + public interface ICamWorkersService : IBaseService + { + List GetList(CamWorkersQueryDto parm); + + CamWorkers GetInfo(long Id); + + + CamWorkers AddCamWorkers(CamWorkers parm); + + + List ExportList(CamWorkersQueryDto parm); + } +} diff --git a/ZR.Service/Business/IBusinessService/ICamWorkrecordService.cs b/ZR.Service/Business/IBusinessService/ICamWorkrecordService.cs index 96d33ac..a0f3e6c 100644 --- a/ZR.Service/Business/IBusinessService/ICamWorkrecordService.cs +++ b/ZR.Service/Business/IBusinessService/ICamWorkrecordService.cs @@ -16,6 +16,6 @@ namespace ZR.Service.Business.IBusinessService CamWorkrecord AddCamWorkrecord(CamWorkrecord parm); int UpdateCamWorkrecord(CamWorkrecord parm); - + PagedInfo ExportList(CamWorkrecordQueryDto parm); } }