Browse Source

Merge branch 'develop' of http://132.232.92.186:3000/XinXiBu/OA2023 into develop

yuanrf 3 days ago
parent
commit
f6e6d2e6df

+ 3 - 2
OASystem/EntitySync/Program.cs

@@ -1,4 +1,5 @@
 using OASystem.Domain.Entities.Groups;
+using OASystem.Domain.Entities.PersonnelModule;
 using OASystem.Domain.Entities.Resource;
 using SqlSugar;
 
@@ -126,7 +127,7 @@ db.CodeFirst.SetStringDefaultLength(50).BackupTable().InitTables(new Type[]
     //typeof(Dis_City), //城市 
     //typeof(Fin_GroupExtraCost), //超支费用 
     //typeof(Pm_TaskAllocation), //任务分配 
-    //typeof(Pm_TaskRelevanceUser), //任务分配关联人员(完成者) 
+    //typeof(Pm_TaskRelevanceUser) //任务分配关联人员(完成者) 
     //typeof(Pm_TaskJobRelevancy), //任务分配关联人员(完成者) 
     //typeof(Crm_TableOperationRecord), //表操作记录 
     //typeof(Grp_InvertedList), //倒推表 
@@ -177,6 +178,6 @@ db.CodeFirst.SetStringDefaultLength(50).BackupTable().InitTables(new Type[]
     //typeof(Grp_ProcessNode),//流程节点
     //typeof(Grp_VisaProcessSteps_Log),//流程节点 
     //typeof(Grp_ProcessLog),//流程节点 
-    typeof(Grp_FeeEntryAcknowledge),//团组费用录入通知记录表 
+    //typeof(Grp_FeeEntryAcknowledge),//团组费用录入通知记录表 
 });
 Console.WriteLine("数据库结构同步完成!");

+ 0 - 1
OASystem/OASystem.Api/Controllers/BusinessController.cs

@@ -68,7 +68,6 @@ namespace OASystem.API.Controllers
             return Ok(await _groupRep.GetGroupNameList(dto));
         }
 
-
         /// <summary>
         /// 团组信息 团组名称 Page List
         /// </summary>

+ 10 - 6
OASystem/OASystem.Api/Controllers/GroupsController.cs

@@ -24,7 +24,6 @@ using OASystem.API.OAMethodLib.Hub.HubClients;
 using OASystem.API.OAMethodLib.Hub.Hubs;
 using OASystem.API.OAMethodLib.JuHeAPI;
 using OASystem.API.OAMethodLib.KiMiApi;
-using OASystem.API.OAMethodLib.Logging;
 using OASystem.API.OAMethodLib.QiYeWeChatAPI.AppNotice;
 using OASystem.Domain.AesEncryption;
 using OASystem.Domain.Attributes;
@@ -43,6 +42,7 @@ using OASystem.Domain.ViewModels.Groups;
 using OASystem.Domain.ViewModels.JuHeExchangeRate;
 using OASystem.Domain.ViewModels.OCR;
 using OASystem.Domain.ViewModels.SmallFun;
+using OASystem.Infrastructure.Logging;
 using OASystem.Infrastructure.Repositories.CRM;
 using OASystem.Infrastructure.Repositories.Financial;
 using OASystem.Infrastructure.Repositories.Groups;
@@ -205,6 +205,7 @@ namespace OASystem.API.Controllers
         /// <param name="grpOrderPreInfoRep"></param>
         /// <param name="visaProcessRep"></param>
         /// <param name="processOverviewRep"></param>
+        /// <param name="groupSearchService"></param>
         public GroupsController(
             ILogger<GroupsController> logger,
             ITextFileLogger eec_textLogger,
@@ -1301,6 +1302,10 @@ namespace OASystem.API.Controllers
         [ProducesResponseType(typeof(JsonView), StatusCodes.Status200OK)]
         public async Task<IActionResult> PostGroupPageList(GroupPageListDto dto)
         {
+            // 创建Stopwatch实例
+            var stopwatch = new Stopwatch();
+            stopwatch.Start();
+
             #region 参数验证
             if (dto.UserId < 1)
                 return Ok(JsonView(false, "员工Id为空"));
@@ -1402,8 +1407,8 @@ namespace OASystem.API.Controllers
                 PageFuncAuth = pageFunAuthView,
                 Data = delegationList
             };
-
-            return Ok(JsonView(true, "查询成功!", resultView, total));
+            stopwatch.Stop();
+            return Ok(JsonView(true, $"查询成功!耗时:{stopwatch.Elapsed.TotalSeconds:F3}s", resultView, total));
         }
 
         /// <summary>
@@ -1471,7 +1476,6 @@ namespace OASystem.API.Controllers
         [HttpPost]
         public async Task<IActionResult> GetGroupListByWhere(GroupListByWhere dto)
         {
-
             #region  参数验证
             if (dto.UserId < 1) return Ok(JsonView(false, "员工Id为空"));
             if (dto.PageId < 1) return Ok(JsonView(false, "页面Id为空"));
@@ -1578,8 +1582,8 @@ namespace OASystem.API.Controllers
                 PageFuncAuth = pageFunAuthView,
                 Data = _DelegationList
             };
-
-            return Ok(JsonView(true, "查询成功!", _view, total));
+           
+            return Ok(JsonView(true, $"查询成功!", _view, total));
         }
 
         /// <summary>

+ 34 - 27
OASystem/OASystem.Api/Controllers/PersonnelModuleController.cs

@@ -19,6 +19,7 @@ using OASystem.Domain.ViewModels.QiYeWeChat;
 using OASystem.Domain.ViewModels.Statistics;
 using OASystem.Infrastructure.Repositories.Groups;
 using OASystem.Infrastructure.Repositories.PersonnelModule;
+using Org.BouncyCastle.Asn1.Tsp;
 using System.Data;
 using System.Diagnostics;
 using System.Globalization;
@@ -1112,6 +1113,8 @@ From
       ta.CreateUserId,
       u.CnName As CreateUserName,
       ta.CreateTime,
+      ta.Remark,
+      ta.OverTime,
       (
         SELECT
           STUFF(
@@ -1172,10 +1175,15 @@ WHERE
                 //设置编辑权限
                 (bool editPerm, string msg1) = _taskAllocationRep.EditPerm(item.Id, dto.UserId);
                 item.EditPerm = editPerm;
-                //设置任务终止权限
-                (bool taskStopPerm, string msg2) = _taskAllocationRep.TaskStopPerm(item.Id, dto.UserId);
-                item.TaskStopPerm = editPerm;
-
+                //设置任务确认权限
+                if (item.CreateUserId == dto.UserId) item.TaskCompletedPerm = true;
+                //设置已知晓权限
+                (bool havePerm, string msg3) = _taskAllocationRep.TaskHavePerm(item.Id, dto.UserId);
+                item.TaskHavePerm = havePerm;
+                //设置详情权限
+                item.TaskDetailsPerm = _sqlSugar.Queryable<Pm_TaskRelevanceUser>()
+                    .Where(it => it.IsDel == 0 && it.TAId == item.Id && (it.UserId == dto.UserId || it.CreateUserId == dto.UserId))
+                    .Any();
             }
 
             return Ok(JsonView(true, "查询成功!", _view, total));
@@ -1284,35 +1292,34 @@ WHERE
         /// <returns></returns>
         [HttpPost]
         [ProducesResponseType(typeof(JsonView), StatusCodes.Status200OK)]
-        public async Task<IActionResult> PostTaskAllocationSetHaveStatus(TaskAllocationStatusDto dto)
+        public async Task<IActionResult> PostTaskAllocationSetHaveStatus(TaskAllocationSetHaveStatusDto dto)
         {
-            var _view = await _taskAllocationRep.TaskSetHaveStatus(dto.SubId, dto.UserId);
+            var _view = await _taskAllocationRep.TaskSetHaveStatus(dto.Id, dto.UserId);
             if (_view.Code == 0)
             {
                 //发送消息
-                var taskUserData = _taskAllocationRep._sqlSugar.Queryable<Pm_TaskRelevanceUser>().Where(it => it.Id == dto.SubId).First();
-                if (taskUserData != null)
-                {
-                    var taskData = _taskAllocationRep._sqlSugar.Queryable<Pm_TaskAllocation>().Where(it => it.Id == taskUserData.TAId).First();
-
-                    if (taskData != null)
-                    {
-                        var UserName = _taskAllocationRep._sqlSugar.Queryable<Sys_Users>().Where(it => it.Id == taskData.CreateUserId).Select(it => it.CnName).First();
+                var taskInfo = _taskAllocationRep._sqlSugar.Queryable<Pm_TaskAllocation>().Where(it => it.Id == dto.Id).First();
 
-                        string title = $"[{taskData.TaskName}] 进度更新!";
-                        string conten_createUser = $"[{UserName}] 已知晓任务.若需查看,请前往任务页面查看详情!";
-                        string qw_conten_createUser = $"[{UserName}] 已知晓任务!";
+                if (taskInfo != null)
+                {
+                    var taskUserInfos = _taskAllocationRep._sqlSugar.Queryable<Pm_TaskRelevanceUser>().Where(it => it.TAId == dto.Id).ToList();
+                    
+                    var taskUserIds = taskUserInfos.Select(it => it.UserId).ToList();
+                    var taskUserIdStrs = taskUserInfos.Select(x => x.UserId.ToString()).ToList();
 
-                        await GeneralMethod.MessageIssueAndNotification(MessageTypeEnum.TaskProgressUpdate, title, conten_createUser, new List<int>() { taskData.CreateUserId }); //创建人发送消息
+                    var userNames = _taskAllocationRep._sqlSugar.Queryable<Sys_Users>().Where(it => taskUserIds.Contains(it.Id)).Select(it => it.CnName).ToList();
+                    var userNamesLabel = string.Join("、", userNames);
+                    string title = $"[{taskInfo.TaskName}] 进度更新!";
+                    string conten_createUser = $"[{userNamesLabel}] 已知晓任务.若需查看,请前往任务页面查看详情!";
+                    string qw_conten_createUser = $"[{userNamesLabel}] 已知晓任务!";
 
-                        await AppNoticeLibrary.SendUserMsg_Task_ToUser(new List<string>() { taskData.CreateUserId.ToString() }, taskData.DiId, qw_conten_createUser, taskData.CreateUserId);
+                    await GeneralMethod.MessageIssueAndNotification(MessageTypeEnum.TaskProgressUpdate, title, conten_createUser, new List<int>() { taskInfo.CreateUserId }); //创建人发送消息
 
-                        string content = $"请注意任务完成时间!若需查看,请前往任务页面查看详情!";
-                        string yw_content = $"请注意任务完成时间!";
-                        await GeneralMethod.MessageIssueAndNotification(MessageTypeEnum.TaskProgressUpdate, title, content, new List<int>() { taskUserData.UserId }); //设置任务人 发送消息
-                        await AppNoticeLibrary.SendUserMsg_Task_ToUser(new List<string>() { taskUserData.UserId.ToString() }, taskData.DiId, yw_content, taskUserData.UserId);
+                    string content = $"请注意任务完成时间!若需查看,请前往任务页面查看详情!";
+                    string qw_content = $"{userNamesLabel},已知晓 [{taskInfo.TaskName}] 任务!";
+                    await GeneralMethod.MessageIssueAndNotification(MessageTypeEnum.TaskProgressUpdate, title, content, taskUserIds); //设置任务人 发送消息
+                    await AppNoticeLibrary.SendUserMsg_Task_ToUser(new List<string>() { taskInfo.CreateUserId.ToString() }, taskInfo.DiId, qw_content, dto.UserId);
 
-                    }
                 }
 
                 return Ok(JsonView(true, "操作成功!"));
@@ -1329,7 +1336,7 @@ WHERE
         [ProducesResponseType(typeof(JsonView), StatusCodes.Status200OK)]
         public async Task<IActionResult> PostTaskAllocationSetAuditStatus(TaskAllocationSetAuditStatusDto dto)
         {
-            var _view = _taskAllocationRep.TaskSetAuditStatus(dto.Id, dto.UserId, dto.OverTime);
+            var _view = _taskAllocationRep.TaskSetAuditStatus(dto.Id, dto.UserId, dto.OverTime,dto.Remark);
             if (_view.Code == 0)
             {
                 //发送消息
@@ -1344,10 +1351,10 @@ WHERE
 
                         string title = $"[{taskInfo.TaskName}] 进度更新!";
                         string content = $"任务已完成!若需查看,请前往任务页面查看详情!";
-                        string yw_content = $"任务已完成!";
+                        string yw_content = $"已完成 [{taskInfo.TaskName}] 任务!";
                         await GeneralMethod.MessageIssueAndNotification(MessageTypeEnum.TaskProgressUpdate, title, content, userIds); //设置任务人 发送消息
                         var userIdStrs = userIds.Select(x => x.ToString()).ToList();
-                        await AppNoticeLibrary.SendUserMsg_Task_ToUser(userIdStrs, taskInfo.DiId, yw_content, taskInfo.CreateUserId);
+                        await AppNoticeLibrary.SendUserMsg_Task_ToUser(userIdStrs, taskInfo.DiId, yw_content, dto.UserId);
 
                     }
                 }

+ 91 - 1
OASystem/OASystem.Api/Controllers/SystemController.cs

@@ -3,6 +3,7 @@ using NPOI.HPSF;
 using NPOI.POIFS.Crypt;
 using OASystem.API.OAMethodLib;
 using OASystem.API.OAMethodLib.DeepSeekAPI;
+using OASystem.API.OAMethodLib.GenericSearch;
 using OASystem.Domain.AesEncryption;
 using OASystem.Domain.Attributes;
 using OASystem.Domain.Entities.Customer;
@@ -45,6 +46,7 @@ namespace OASystem.API.Controllers
         private readonly List<int> _taskTypeList = new() { 6 };//任务通知 TaskNotification
         private readonly ApprovalProcessRepository _approvalProcessRep;
         private readonly IDeepSeekService _deepSeek;
+        private readonly DynamicSearchService<Fin_DailyFeePayment> _dailyFeeSearchService;
 
         public SystemController(
             CompanyRepository syscom,
@@ -63,7 +65,8 @@ namespace OASystem.API.Controllers
             MessageRepository messageRep,
             SetDataTypeRepository setDataTypeRep,
             ApprovalProcessRepository approvalProcessRep,
-            IDeepSeekService deepSeek
+            IDeepSeekService deepSeek,
+            DynamicSearchService<Fin_DailyFeePayment> dailyFeeSearchService
             )
         {
             _syscomRep = syscom;
@@ -84,7 +87,94 @@ namespace OASystem.API.Controllers
             _config = config;
             _approvalProcessRep = approvalProcessRep;
             _deepSeek = deepSeek;
+            _dailyFeeSearchService = dailyFeeSearchService;
         }
+
+        #region ALL OA 多词条搜索
+
+        /// <summary>
+        ///  日付信息列表 关键字输入提示
+        /// </summary>
+        /// <param name="keyword">关键字</param>
+        /// <param name="auditType">审核类型 0 全部 1 张总未审核</param>
+        /// <returns></returns>
+        [HttpGet]
+        [ProducesResponseType(typeof(JsonView), StatusCodes.Status200OK)]
+        public async Task<IActionResult> DailyFeeKeywordSearch(string keyword,int auditType)
+        {
+            try
+            {
+                // 验证请求参数
+                if (string.IsNullOrEmpty(keyword))
+                {
+                    return Ok(JsonView(true, $"暂无数据!"));
+                }
+
+                var searchFilters = new List<SearchFilter>()
+                    {
+                        new(){Field = "IsDel",Operator="eq",Value="0" }
+                    };
+
+                //张总未审核过滤
+                if (auditType == 1)
+                {
+                    searchFilters.Add(new() { Field = "MAudit", Operator = "eq", Value = "0" });
+                }
+
+                var searchRequest = new DynamicSearchRequest
+                {
+                    Keyword = keyword,
+                    RequireAllSingleChars = true,
+                    PageIndex = 1,
+                    PageSize = 999999,
+                    FieldWeights = new Dictionary<string, int>
+                    {
+                        { "Instructions", 10 }
+                    },
+                    Filters = searchFilters,
+                    OrderBy = "CreateTime",
+                    //ReturnFields = new List<string>() { "TeamName", "ClientUnit", "ClientName" }
+                };
+
+                // 验证字段配置
+                var validation = _dailyFeeSearchService.ValidateFieldConfig(
+                    searchRequest.FieldWeights,
+                    searchRequest.ReturnFields);
+
+                if (!validation.IsValid)
+                {
+                    return Ok(JsonView(true, $"暂无数据!{validation.Message}"));
+                }
+
+                var result = await _dailyFeeSearchService.SearchAsync(searchRequest);
+
+                if (result.Success)
+                {
+                    var data = new List<dynamic>();
+
+                    foreach (var item in result.Items)
+                    {
+                        data.Add(new
+                        {
+                            item.Data.Instructions,
+                        });
+                    }
+
+                    return Ok(JsonView(true, result.Message, data, data.Count));
+                }
+
+                return Ok(JsonView(true, result.Message));
+            }
+            catch (Exception ex)
+            {
+                return Ok(JsonView(true, $"搜索服务暂时不可用!"));
+            }
+
+        }
+
+        #endregion
+
+
         #region 消息
 
         /// <summary>

+ 0 - 22
OASystem/OASystem.Api/OAMethodLib/Logging/ITextFileLogger.cs

@@ -1,22 +0,0 @@
-namespace OASystem.API.OAMethodLib.Logging
-{
-    /// <summary>
-    /// 出入境费用文本日志接口
-    /// </summary>
-    public interface ITextFileLogger
-    {
-        void LogInformation(string message, params object[] args);
-        void LogWarning(string message, params object[] args);
-        void LogError(Exception ex, string message, params object[] args);
-    }
-
-    /// <summary>
-    /// 团组不走操作日志接口
-    /// </summary>
-    public interface IGroupTextFileLogger
-    {
-        void LogInformation(string message, params object[] args);
-        void LogWarning(string message, params object[] args);
-        void LogError(Exception ex, string message, params object[] args);
-    }
-}

+ 1 - 1
OASystem/OASystem.Api/OAMethodLib/QiYeWeChatAPI/AppNotice/Library.cs

@@ -7,7 +7,7 @@ using OASystem.Domain.ViewModels.Groups;
 using OASystem.Domain.ViewModels.QiYeWeChat;
 using OASystem.Infrastructure.Repositories.Groups;
 using OASystem.Domain.Entities.WorkOrder;
-using OASystem.API.OAMethodLib.Logging;
+using OASystem.Infrastructure.Logging;
 
 namespace OASystem.API.OAMethodLib.QiYeWeChatAPI.AppNotice
 {

+ 2 - 2
OASystem/OASystem.Api/OAMethodLib/Quartz/Business/TaskAssignment.cs

@@ -36,7 +36,7 @@ namespace OASystem.API.OAMethodLib.Quartz.Business
                                     .Where(it =>
                                                     it.IsDel == 0 &&
                                                     primaryIds.Contains(it.TAId) &&
-                                                    it.TaskStatus <= TaskerEnum.UnderWay
+                                                    it.TaskStatus <= TaskEnum.UnderWay
                                             )
                                     .ToList();
 
@@ -45,7 +45,7 @@ namespace OASystem.API.OAMethodLib.Quartz.Business
                     foreach (var item in subData)
                     {
                         item.OverTime = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss");
-                        item.TaskStatus = TaskerEnum.UnFinished;
+                        item.TaskStatus = TaskEnum.UnFinished;
                         item.Cause = string.Format(@"任务没有提交完成或者超时,由系统设置任务未完成");
                     }
 

+ 2 - 2
OASystem/OASystem.Api/OAMethodLib/Quartz/Business/TaskNotification.cs

@@ -78,8 +78,8 @@ namespace OASystem.API.OAMethodLib.Quartz.Business
                         }
                         else
                         {
-                            if (subItem.TaskStatus == TaskerEnum.NotStarted) realityStartTime = "未开始";
-                            else if (subItem.TaskStatus == TaskerEnum.HaveKnown) realityStartTime = "已知晓";
+                            if (subItem.TaskStatus == TaskEnum.NotStarted) realityStartTime = "未开始";
+                            else if (subItem.TaskStatus == TaskEnum.UnderWay) realityStartTime = "已知晓";
                         }
 
                         var userData = userDatas.Where(it => it.Id == subItem.UserId).FirstOrDefault();

+ 28 - 4
OASystem/OASystem.Api/Program.cs

@@ -3,7 +3,6 @@ using Microsoft.AspNetCore.Http.Features;
 using Microsoft.AspNetCore.ResponseCompression;
 using Microsoft.AspNetCore.Server.Kestrel.Core;
 using Microsoft.Extensions.DependencyInjection.Extensions;
-using Microsoft.IdentityModel.Tokens;
 using OASystem.API.Middlewares;
 using OASystem.API.OAMethodLib;
 using OASystem.API.OAMethodLib.AMapApi;
@@ -12,10 +11,10 @@ using OASystem.API.OAMethodLib.DeepSeekAPI;
 using OASystem.API.OAMethodLib.GenericSearch;
 using OASystem.API.OAMethodLib.Hub.Hubs;
 using OASystem.API.OAMethodLib.JuHeAPI;
-using OASystem.API.OAMethodLib.Logging;
 using OASystem.API.OAMethodLib.QiYeWeChatAPI;
 using OASystem.API.OAMethodLib.Quartz.Jobs;
 using OASystem.API.OAMethodLib.SignalR.HubService;
+using OASystem.Infrastructure.Logging;
 using Quartz;
 using Quartz.Impl;
 using Quartz.Spi;
@@ -216,7 +215,7 @@ builder.Services.AddScoped(options =>
             //获取无参数化SQL 影响性能只适合调试
             //UtilMethods.GetSqlString(DbType.SqlServer, sql, pars);
 
-           
+
             if (pars != null || pars.Length > 0)
             {
                 Console.WriteLine("============== 完整 SQL ==============");
@@ -236,7 +235,7 @@ builder.Services.AddScoped(options =>
                         };
                         resultSql = resultSql.Replace(param.ParameterName, formattedValue);
                     }
-                    
+
                 }
                 Console.WriteLine(resultSql);
                 Console.WriteLine("=====================================");
@@ -442,11 +441,36 @@ var groupStepOP_TextLogger = new LoggerConfiguration()
 
 #endregion
 
+#region 任务分配操作 专用记录器
+
+// 指定磁盘绝对路径(示例:D盘的AppLogs文件夹)
+var taskLogDir = @"D:\OASystem\Logs\TaskAllocation";
+
+// 自动创建目录(如果不存在)
+try
+{
+    Directory.CreateDirectory(taskLogDir);
+    Log.Information($"日志目录已创建/确认存在: {taskLogDir}");
+}
+catch (Exception ex)
+{
+    Log.Fatal($"无法创建日志目录 {taskLogDir}: {ex.Message}");
+    throw;
+}
+
+var task_TextLogger = new LoggerConfiguration()
+    .MinimumLevel.Information()
+    .WriteTo.File(Path.Combine(taskLogDir, "text-records-.txt"), rollingInterval: RollingInterval.Month)
+    .CreateLogger();
+
+#endregion
+
 // 配置Serilog为Log;
 builder.Host.UseSerilog();
 
 builder.Services.AddSingleton<ITextFileLogger>(new TextFileLogger(eec_TextLogger));
 builder.Services.AddSingleton<IGroupTextFileLogger>(new GroupTextFileLogger(groupStepOP_TextLogger));
+builder.Services.AddSingleton<ITaskTextFileLogger>(new TaskTextFileLogger(task_TextLogger));
 #endregion
 
 #region 引入注册Autofac Module

+ 14 - 0
OASystem/OASystem.Domain/Dtos/PersonnelModule/TaskAllocationDto.cs

@@ -177,6 +177,18 @@ namespace OASystem.Domain.Dtos.PersonnelModule
         /// </summary>
         public int SubId { get; set; }
     }
+    //
+    /// <summary>
+    /// 任务分配 
+    /// 任务状态更改
+    /// </summary>
+    public class TaskAllocationSetHaveStatusDto : UserPageFuncDtoBase
+    {
+        /// <summary>
+        /// Id
+        /// </summary>
+        public int Id { get; set; }
+    }
 
     /// <summary>
     /// 任务发布者 单人设置审批状态
@@ -192,6 +204,8 @@ namespace OASystem.Domain.Dtos.PersonnelModule
         /// 实际结束时间
         /// </summary>
         public string OverTime { get; set; }
+
+        public string Remark { get; set; }
     }
 
     /// <summary>

+ 1 - 1
OASystem/OASystem.Domain/Entities/PersonnelModule/Pm_TaskRelevanceUser.cs

@@ -45,7 +45,7 @@ namespace OASystem.Domain.Entities.PersonnelModule
         /// -1 未开始 0 已知晓 1 进行中 2 待审核 3 未完成  4 已完成 5任务中止
         /// </summary>
         [SugarColumn(IsNullable = true, ColumnDataType = "int")]
-        public TaskerEnum TaskStatus { get; set; } = TaskerEnum.NotStarted;
+        public TaskEnum TaskStatus { get; set; } = TaskEnum.NotStarted;
 
         /// <summary>
         /// 未完成原因

+ 1 - 1
OASystem/OASystem.Domain/Enums/TaskEnum.cs

@@ -47,7 +47,7 @@ namespace OASystem.Domain.Enums
     /// <summary>
     /// 任务者状态
     /// </summary>
-    public enum TaskerEnum : int
+    public enum TaskerEnum1 : int
     {
         /// <summary>
         /// 任务指派状态

+ 16 - 4
OASystem/OASystem.Domain/ViewModels/PersonnelModule/TaskAllocationView.cs

@@ -190,14 +190,24 @@ namespace OASystem.Domain.ViewModels.PersonnelModule
         public bool EditPerm { get; set; } = false;
 
         /// <summary>
-        /// 任务终止权限
+        /// 任务完成权限
         /// </summary>
-        public bool TaskStopPerm { get; set; } = false;
+        public bool TaskCompletedPerm { get; set; } = false;
 
         /// <summary>
-        /// 已知晓权限
+        /// 详情/已知晓权限
         /// </summary>
         public bool TaskHavePerm { get; set; } = false;
+
+        /// <summary>
+        /// 详情权限
+        /// </summary>
+        public bool TaskDetailsPerm { get; set; } = false;
+
+        /// <summary>
+        /// 备注
+        /// </summary>
+        public string Remark { get; set; }
     }
 
     /// <summary>
@@ -261,6 +271,8 @@ namespace OASystem.Domain.ViewModels.PersonnelModule
         public List<TaskUserDetailsView>? UserTaskInfos { get; set; }
 
         public string Remark { get; set; }
+
+        public int TaskType { get; set; }
     }
 
 
@@ -330,7 +342,7 @@ namespace OASystem.Domain.ViewModels.PersonnelModule
         /// <summary>
         /// 任务状态
         /// </summary>
-        public TaskerEnum TaskStatus { get; set; }
+        public TaskEnum TaskStatus { get; set; }
 
         /// <summary>
         /// 未完成原因

+ 31 - 0
OASystem/OASystem.Infrastructure/Logging/ITextFileLogger.cs

@@ -0,0 +1,31 @@
+namespace OASystem.Infrastructure.Logging
+{
+
+    public interface IBaseTextFileLogger
+    {
+        void LogInformation(string message, params object[] args);
+        void LogWarning(string message, params object[] args);
+        void LogError(Exception ex, string message, params object[] args);
+    }
+
+    /// <summary>
+    /// 出入境费用文本日志接口
+    /// </summary>
+    public interface ITextFileLogger:IBaseTextFileLogger
+    {
+    }
+
+    /// <summary>
+    /// 团组步骤操作日志接口
+    /// </summary>
+    public interface IGroupTextFileLogger : IBaseTextFileLogger
+    {
+    }
+
+    /// <summary>
+    /// 团组步骤操作日志接口
+    /// </summary>
+    public interface ITaskTextFileLogger : IBaseTextFileLogger
+    {
+    }
+}

+ 21 - 2
OASystem/OASystem.Api/OAMethodLib/Logging/TextFileLogger.cs

@@ -1,7 +1,8 @@
 using ILogger = Serilog.ILogger;
 
-namespace OASystem.API.OAMethodLib.Logging
+namespace OASystem.Infrastructure.Logging
 {
+   
     /// <summary>
     /// 出入境费用明细日志记录
     /// </summary>
@@ -21,7 +22,7 @@ namespace OASystem.API.OAMethodLib.Logging
     }
 
     /// <summary>
-    /// 团组不走操作日志
+    /// 团组步骤操作日志
     /// </summary>
     public class GroupTextFileLogger : IGroupTextFileLogger
     {
@@ -37,4 +38,22 @@ namespace OASystem.API.OAMethodLib.Logging
         public void LogError(Exception ex, string message, params object[] args)
             => _logger.Error(ex, message, args);
     }
+
+    /// <summary>
+    /// 任务分配操作日志
+    /// </summary>
+    public class TaskTextFileLogger : ITaskTextFileLogger
+    {
+        private readonly ILogger _logger;
+        public TaskTextFileLogger(ILogger logger) => _logger = logger;
+
+        public void LogInformation(string message, params object[] args)
+            => _logger.Information(message, args);
+
+        public void LogWarning(string message, params object[] args)
+            => _logger.Warning(message, args);
+
+        public void LogError(Exception ex, string message, params object[] args)
+            => _logger.Error(ex, message, args);
+    }
 }

+ 340 - 47
OASystem/OASystem.Infrastructure/Repositories/PersonnelModule/TaskAllocationRepository.cs

@@ -8,6 +8,7 @@ using OASystem.Domain.Entities.Groups;
 using OASystem.Domain.Entities.PersonnelModule;
 using OASystem.Domain.Entities.System;
 using OASystem.Domain.ViewModels.PersonnelModule;
+using OASystem.Infrastructure.Logging;
 using Org.BouncyCastle.Asn1.Tsp;
 using Org.BouncyCastle.Ocsp;
 using SqlSugar;
@@ -15,7 +16,9 @@ using System;
 using System.Collections.Generic;
 using System.Linq;
 using System.Net.NetworkInformation;
+using System.Reflection;
 using System.Text;
+using System.Text.Json.Serialization;
 using System.Threading.Tasks;
 
 namespace OASystem.Infrastructure.Repositories.PersonnelModule
@@ -28,12 +31,14 @@ namespace OASystem.Infrastructure.Repositories.PersonnelModule
     {
         private readonly IMapper _mapper;
         private Result _result;
+        private readonly ITaskTextFileLogger _taskTextFileLogger;
 
-        public TaskAllocationRepository(SqlSugarClient sqlSugar, IMapper mapper)
+        public TaskAllocationRepository(SqlSugarClient sqlSugar, IMapper mapper, ITaskTextFileLogger taskTextFileLogger)
             : base(sqlSugar)
         {
             _mapper = mapper;
             _result = new Result() { Code = -1, Msg = "操作失败!" };
+            _taskTextFileLogger = taskTextFileLogger;
         }
 
         /// <summary>
@@ -196,6 +201,7 @@ namespace OASystem.Infrastructure.Repositories.PersonnelModule
                         CreateTime = it.CreateTime,
                         TaskName = it.TaskName,
                         TaskContent = it.TaskContent,
+                        TaskType = it.TaskType,
                         TaskPriority = it.TaskPriority,
                         PredictBeginTime = it.PredictBeginTime,
                         PredictEndTime = it.PredictEndTime,
@@ -325,6 +331,41 @@ namespace OASystem.Infrastructure.Repositories.PersonnelModule
             return (true, string.Empty);
         }
 
+        /// <summary>
+        /// 任务知晓权限验证
+        /// </summary>
+        public (bool CanEdit, string Message) TaskHavePerm(int taskId, int currentUserId)
+        {
+            var taskInfo = _sqlSugar.Queryable<Pm_TaskAllocation>().First(x => x.Id == taskId && x.IsDel == 0);
+
+            if (taskInfo == null)
+                return (false, "任务不存在!");
+
+            var taskerInfo = _sqlSugar.Queryable<Pm_TaskRelevanceUser>().First(x => x.TAId == taskId && x.UserId == currentUserId && x.IsDel == 0);
+            if (taskerInfo == null)
+                return (false, "任务指派单不存在!");
+
+            if (taskerInfo.UserId != currentUserId)
+                return (false, "只有任务归属者可设置“已知晓”状态!");
+
+            // 检查当前状态是否设置已知晓
+            //if (taskerInfo.TaskStatus == TaskerEnum.HaveKnown)
+            //{
+            //    return (false, "当前状态已设置,无需重复操作!");
+            //}
+
+            //if (taskInfo.Status == TaskEnum.UnFinished)
+            //{
+            //    return (false, "当前状态 “未完成”,不可设置该状态!");
+            //}
+            //if (taskInfo.Status == TaskEnum.Finished)
+            //{
+            //    return (false, "当前状态 “已完成”,不可设置该状态!");
+            //}
+
+            return (true, string.Empty);
+        }
+
         /// <summary>
         /// 安全解析字符串为 DateTime?
         /// </summary>
@@ -365,13 +406,15 @@ namespace OASystem.Infrastructure.Repositories.PersonnelModule
                     _TaskRelevanceUsers.Add(new Pm_TaskRelevanceUser() {
                         TAId = dto.Id,
                         UserId = item,
-                        TaskStatus = TaskerEnum.NotStarted,
+                        TaskStatus = TaskEnum.NotStarted,
                         CreateUserId = dto.UserId,
                     });
                 }
 
                 #endregion
 
+                var createUserName = _sqlSugar.Queryable<Sys_Users>().Where(x => x.Id == dto.UserId).First()?.CnName ?? "-";
+
                 if (dto.Id == 0) //添加
                 {
                     //// 1 按 任务名称 查询重
@@ -388,7 +431,8 @@ namespace OASystem.Infrastructure.Repositories.PersonnelModule
                     if (addId < 1)
                     {
                         _sqlSugar.RollbackTran();
-                        _result.Msg = string.Format("任务发布失败!");
+                        _result.Msg = string.Format("任务发布失败!"); 
+                        _taskTextFileLogger.LogInformation("任务新增[失败],任务名称:{TaskName},创建人:{CreateUserName}", _TaskAllocation.TaskName, createUserName);
                         return _result;
                     }
 
@@ -403,18 +447,22 @@ namespace OASystem.Infrastructure.Repositories.PersonnelModule
                     {
                         _sqlSugar.RollbackTran();
                         _result.Msg = string.Format("任务发布失败!");
+                        _taskTextFileLogger.LogInformation("任务新增[失败],任务名称:{TaskName},创建人:{CreateUserName}", _TaskAllocation.TaskName, createUserName);
                         return _result;
                     }
 
                     _result.Code = 0;
                     _result.Msg = "添加成功!";
+                    _taskTextFileLogger.LogInformation("任务新增[成功],任务名称:{TaskName},创建人:{CreateUserName}", _TaskAllocation.TaskName, createUserName);
+
                     _sqlSugar.CommitTran();
                 }
                 else if (dto.Id > 0) //修改
                 {
                     _sqlSugar.BeginTran();
 
-                    #region 编辑验证 1. 仅创建者可以修改 2.状态完成不可修改
+                   
+                    #region 编辑验证 1. 仅创建者可以修改 
 
                     var taskInfo = await _sqlSugar
                         .Queryable<Pm_TaskAllocation>()
@@ -427,13 +475,27 @@ namespace OASystem.Infrastructure.Repositories.PersonnelModule
                         if (!isEdit)
                         {
                             _result.Msg = msg;
+                            _taskTextFileLogger.LogInformation("任务编辑[无操作权限],任务名称:{TaskName},创建人:{CreateUserName}", _TaskAllocation.TaskName, createUserName);
+
+                            _sqlSugar.RollbackTran();
                             return _result;
                         }
                     }
 
                     #endregion
-
-                    int updateStatus1 = await _sqlSugar.Updateable<Pm_TaskAllocation>(_TaskAllocation)
+                    var mainTaskInfoOld = new Pm_TaskAllocation() {
+                        DepId = taskInfo.DepId,
+                        DiId = taskInfo.DiId,
+                        TaskType = taskInfo.TaskType,
+                        TaskPriority = taskInfo.TaskPriority,
+                        TaskName = taskInfo.TaskName,
+                        TaskContent = taskInfo.TaskContent,
+                        PredictBeginTime = taskInfo.PredictBeginTime,
+                        PredictEndTime = taskInfo.PredictEndTime,
+                        IsIntoPerformance = taskInfo.IsIntoPerformance
+                    };
+
+                   int updateStatus1 = await _sqlSugar.Updateable<Pm_TaskAllocation>(_TaskAllocation)
                         .UpdateColumns(it => new
                         {
                             it.DepId,
@@ -452,6 +514,8 @@ namespace OASystem.Infrastructure.Repositories.PersonnelModule
                     {
                         _sqlSugar.RollbackTran();
                         _result.Msg = string.Format("任务编辑失败!");
+                        _taskTextFileLogger.LogInformation("任务编辑[失败],任务名称:{TaskName},创建人:{CreateUserName}", _TaskAllocation.TaskName, createUserName);
+
                         return _result;
                     }
 
@@ -468,6 +532,8 @@ namespace OASystem.Infrastructure.Repositories.PersonnelModule
                         {
                             _sqlSugar.RollbackTran();
                             _result.Msg = string.Format("任务编辑失败!");
+                            _taskTextFileLogger.LogInformation("任务编辑[失败],任务名称:{TaskName},创建人:{CreateUserName}", _TaskAllocation.TaskName, createUserName);
+
                             return _result;
                         }
                     }
@@ -518,17 +584,36 @@ namespace OASystem.Infrastructure.Repositories.PersonnelModule
                                 {
                                     _sqlSugar.RollbackTran();
                                     _result.Msg = string.Format("任务编辑失败!");
+                                    _taskTextFileLogger.LogInformation("任务编辑[失败],任务名称:{TaskName},创建人:{CreateUserName}", _TaskAllocation.TaskName, createUserName);
+
                                     return _result;
                                 }
                             }
                         }
                     }
 
+                    var mainTaskInfoNew = new Pm_TaskAllocation()
+                    {
+                        DepId = _TaskAllocation.DepId,
+                        DiId = _TaskAllocation.DiId,
+                        TaskType = _TaskAllocation.TaskType,
+                        TaskPriority = _TaskAllocation.TaskPriority,
+                        TaskName = _TaskAllocation.TaskName,
+                        TaskContent = _TaskAllocation.TaskContent,
+                        PredictBeginTime = _TaskAllocation.PredictBeginTime,
+                        PredictEndTime = _TaskAllocation.PredictEndTime,
+                        IsIntoPerformance = _TaskAllocation.IsIntoPerformance
+                    }; ;
+
                     /*
                      * 发送消息
                      */
                     _result.Code = 0;
                     _result.Msg = "编辑成功!";
+                    var changeMsg = ChangeMsg(mainTaskInfoOld, mainTaskInfoNew);
+
+                    _taskTextFileLogger.LogInformation("任务完成设置[成功],任务名称:{TaskName},操作者:{OperatorName}{ChangeMsg}", _TaskAllocation.TaskName, createUserName, changeMsg);
+
                     _sqlSugar.CommitTran();
                 }
                 else _result.Msg = string.Format("请传入有效的Id参数!");
@@ -590,7 +675,7 @@ namespace OASystem.Infrastructure.Repositories.PersonnelModule
             _sqlSugar.BeginTran();
 
             var update1 = await _sqlSugar.Updateable<Pm_TaskRelevanceUser>()
-                                         .SetColumns(it => it.TaskStatus == TaskerEnum.HaveKnown)
+                                         .SetColumns(it => it.TaskStatus == TaskEnum.UnderWay)
                                          .ExecuteCommandAsync();
             if (update1 < 1)
             {
@@ -624,7 +709,7 @@ namespace OASystem.Infrastructure.Repositories.PersonnelModule
                 _result.Msg = string.Format("该任务不在!");
                 return _result;
             }
-            if (selectData.TaskStatus >= TaskerEnum.UnderWay)
+            if (selectData.TaskStatus >= TaskEnum.UnderWay)
             {
                 _result.Msg = string.Format("该任务已知晓,不可重复设置!");
                 return _result;
@@ -632,7 +717,7 @@ namespace OASystem.Infrastructure.Repositories.PersonnelModule
 
             _sqlSugar.BeginTran();
             var update1 = await _sqlSugar.Updateable<Pm_TaskRelevanceUser>()
-                                         .SetColumns(it => it.TaskStatus == TaskerEnum.UnderWay)
+                                         .SetColumns(it => it.TaskStatus == TaskEnum.UnderWay)
                                          .SetColumns(it => it.BeginTime == DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"))
                                          .Where(it => it.TAId == id)
                                          .Where(it => it.UserId == userId )
@@ -683,14 +768,14 @@ namespace OASystem.Infrastructure.Repositories.PersonnelModule
                 return _result;
             }
             
-            if (selectData.TaskStatus >= TaskerEnum.WaitConfirm)
+            if (selectData.TaskStatus >= TaskEnum.WaitConfirm)
             {
                 _result.Msg = string.Format("该任务已提交待审核状态,不可重复提交!");
                 return _result;
             }
             _sqlSugar.BeginTran();
             var update1 = await _sqlSugar.Updateable<Pm_TaskRelevanceUser>()
-                                         .SetColumns(it => it.TaskStatus == TaskerEnum.WaitConfirm)
+                                         .SetColumns(it => it.TaskStatus == TaskEnum.WaitConfirm)
                                          .SetColumns(it => it.OverTime == DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"))
                                          .Where(it => it.TAId == id)
                                          .Where(it => it.UserId == userId)
@@ -732,31 +817,45 @@ namespace OASystem.Infrastructure.Repositories.PersonnelModule
                 return _result;
             }
 
-            var taskUserInfo = await _sqlSugar.Queryable<Pm_TaskRelevanceUser>().Where(it => it.IsDel == 0 && it.TAId == id && it.UserId == userId).FirstAsync();
-            if (taskUserInfo == null)
+            //状态校验
+            (bool havePerm, string msg3) = TaskHavePerm(id, userId);
+            if (!havePerm)
             {
-                _result.Msg = string.Format("该任务不存在!");
+                _result.Msg = msg3;
                 return _result;
             }
-            var taskerId = taskUserInfo.Id;
 
-            //状态确认
-            if (taskUserInfo.TaskStatus == TaskerEnum.HaveKnown)
+            _sqlSugar.BeginTran();
+            var taskName = await _sqlSugar.Queryable<Pm_TaskAllocation>().Where(it => it.IsDel == 0 && it.Id == id).Select(it => it.TaskName).FirstAsync();
+            var operatorName = await _sqlSugar.Queryable<Sys_Users>().Where(it => it.IsDel == 0 && it.Id == userId).Select(it => it.CnName).FirstAsync();
+            var update1 = await _sqlSugar.Updateable<Pm_TaskRelevanceUser>()
+                .SetColumns(it => it.TaskStatus == TaskEnum.UnderWay)
+                .Where(it => it.TAId == id && it.UserId == userId)
+                .ExecuteCommandAsync();
+            if (update1 < 1)
             {
-                _result.Msg = string.Format("已设置“已知晓”状态,不可重复设置!");
+                _result.Msg = string.Format("操作失败!");
+
+                _taskTextFileLogger.LogInformation("任务知晓设置[失败],任务名称:{TaskName},操作者:{OperatorName}", taskName, operatorName);
+
+                _sqlSugar.RollbackTran();
                 return _result;
             }
 
-            var update1 = await _sqlSugar.Updateable<Pm_TaskRelevanceUser>()
-                .SetColumns(it => it.TaskStatus == TaskerEnum.HaveKnown)
-                .Where(it => it.Id == taskerId && it.UserId == userId)
+            var update2 = await _sqlSugar.Updateable<Pm_TaskAllocation>()
+                .SetColumns(it => it.Status == TaskEnum.UnderWay)
+                .Where(it => it.Id == id)
                 .ExecuteCommandAsync();
-            if (update1 < 1)
+            if (update2 < 1)
             {
                 _result.Msg = string.Format("操作失败!");
+                _taskTextFileLogger.LogInformation("任务知晓设置[失败],任务名称:{TaskName},操作者:{OperatorName}", taskName, operatorName);
+                _sqlSugar.RollbackTran();
                 return _result;
             }
+
             _result.Msg = string.Format("操作成功!");
+            _taskTextFileLogger.LogInformation("任务知晓设置[成功],任务名称:{TaskName},操作者:{OperatorName}", taskName, operatorName);
             _result.Code = 0;
             _sqlSugar.CommitTran();
 
@@ -768,7 +867,7 @@ namespace OASystem.Infrastructure.Repositories.PersonnelModule
         /// </summary>
         /// <param name="id"></param>
         /// <returns></returns>
-        public Result TaskSetAuditStatus(int id,int userId,string overTime)
+        public Result TaskSetAuditStatus(int id,int userId,string overTime,string remark)
         {
             if (id < 1)
             {
@@ -793,6 +892,9 @@ namespace OASystem.Infrastructure.Repositories.PersonnelModule
 
             _sqlSugar.BeginTran();
 
+            var taskName =  _sqlSugar.Queryable<Pm_TaskAllocation>().Where(it => it.IsDel == 0 && it.Id == id).Select(it => it.TaskName).First();
+            var operatorName =  _sqlSugar.Queryable<Sys_Users>().Where(it => it.IsDel == 0 && it.Id == userId).Select(it => it.CnName).First();
+
             try
             {
                 //状态验证
@@ -811,24 +913,27 @@ namespace OASystem.Infrastructure.Repositories.PersonnelModule
                 if (subTaskInfo.CreateUserId != userId)
                 {
                     _result.Msg = string.Format("只有任务创建者可审批'已完成'状态!");
+                    _taskTextFileLogger.LogInformation("任务完成设置[尝试审批],任务名称:{TaskName},操作者:{OperatorName}", taskName, operatorName);
                     return _result;
                 }
 
                 //不可重复设置状态
-                if (subTaskInfo.TaskStatus == TaskerEnum.Finished)
-                {
-                    _result.Msg = string.Format("“已完成”状态,已设置不可重复操作!");
-                    return _result;
-                }
+                //if (subTaskInfo.TaskStatus == TaskerEnum.Finished)
+                //{
+                //    _result.Msg = string.Format("“已完成”状态,已设置不可重复操作!");
+                //    return _result;
+                //}
 
                 var subTaskUpd = _sqlSugar.Updateable<Pm_TaskRelevanceUser>()
-                    .SetColumns(it => it.TaskStatus == TaskerEnum.Finished)
+                    .SetColumns(it => it.TaskStatus == TaskEnum.Finished)
                     .SetColumns(it => it.OverTime == overTime)
+                    .SetColumns(it => it.Remark == remark)
                     .Where(it => it.Id == taskerId)
                     .ExecuteCommand();
                 if (subTaskUpd < 1)
                 {
                     _result.Msg = string.Format("操作失败!");
+                    _taskTextFileLogger.LogInformation("任务完成设置[失败],任务名称:{TaskName},操作者:{OperatorName}", taskName, operatorName);
                     _sqlSugar.RollbackTran();
                     return _result;
                 }
@@ -841,35 +946,59 @@ namespace OASystem.Infrastructure.Repositories.PersonnelModule
                     .Select(x => new
                     {
                         x.Id,
+                        x.UserId,
                         x.TaskStatus
                     })
                     .ToList();
 
+                var mainTaskInfoOld = _sqlSugar.Queryable<Pm_TaskAllocation>()
+                    .Where(x => x.Id == mainTaskId && x.IsDel == 0)
+                    .Select(x => new Pm_TaskAllocation
+                    {
+                        OverTime = x.OverTime,
+                        Status = x.Status,
+                        Remark = x.Remark
+                    })
+                    .First();
+                var mainTaskInfoNew = new Pm_TaskAllocation();
+
                 // 计算任务状态统计
                 int totalCount = allRelevanceTasks.Count;
 
-                // 已完成状态数量
-                int finishedCount = allRelevanceTasks.Count(x => x.TaskStatus == TaskerEnum.Finished);
-                // 未完成状态数量
-                int unfinishedCount = allRelevanceTasks.Count(x => x.TaskStatus == TaskerEnum.UnFinished);
+                // 未开始 数量
+                int notStartedCount = allRelevanceTasks.Count(x => x.TaskStatus <= TaskEnum.NotStarted);
+                int underWayCount = allRelevanceTasks.Count(x => x.TaskStatus > TaskEnum.NotStarted);
+
+                if (notStartedCount > 0)
+                {
+                    //其他人未设置已知晓 不可设置 完成状态
+                    var userIds = allRelevanceTasks.Where(x => x.TaskStatus < TaskEnum.UnderWay).Select(x => x.UserId).ToList();
+                    var names = _sqlSugar.Queryable<Sys_Users>()
+                        .Where(x => userIds.Contains(x.Id))
+                        .Select(x => x.CnName)
+                        .ToList();
+
+                    string userLabel = string.Join("、",names);
 
-                // 结束状态数量(已完成 + 未完成)
-                int endedCount = finishedCount + unfinishedCount;
+                    _result.Msg = string.Format($"{userLabel} 未点击已知晓,不可设置任务完成。");
+                    _sqlSugar.RollbackTran();
+                    return _result;
+                }
 
                 // 判断是否所有子任务均处于结束状态 是 则更新主任务状态
-                bool allTasksInEndStatus = totalCount == endedCount;
+                bool allTasksInEndStatus = totalCount == underWayCount;
                 if (allTasksInEndStatus)
                 {
                     TaskEnum newMainTaskStatus;
 
-                    if (unfinishedCount > 0)
+                    if (notStartedCount > 0)
                     {
                         // 存在未完成的子任务
                         newMainTaskStatus = TaskEnum.UnFinished;
                     }
-                    else if (finishedCount == totalCount)
+                    else if (underWayCount == totalCount)
                     {
-                        // 所有子任务都已完成
+                        // 所有子任务都在进行中
                         newMainTaskStatus = TaskEnum.Finished;
                     }
                     else
@@ -882,7 +1011,8 @@ namespace OASystem.Infrastructure.Repositories.PersonnelModule
                         .SetColumns(x => new Pm_TaskAllocation
                         {
                             Status = newMainTaskStatus,
-                            OverTime = overTime
+                            OverTime = overTime,
+                            Remark = remark
                         })
                         .Where(x => x.Id == mainTaskId && x.IsDel == 0)
                         .ExecuteCommand();
@@ -890,14 +1020,26 @@ namespace OASystem.Infrastructure.Repositories.PersonnelModule
                     if (rowsAffected <= 0)
                     {
                         _result.Msg = string.Format("更新主任务状态失败!");
+                        _taskTextFileLogger.LogInformation("任务完成设置[失败],任务名称:{TaskName},操作者:{OperatorName}", taskName, operatorName);
                         _sqlSugar.RollbackTran();
                         return _result;
                     }
-                }
+                    mainTaskInfoNew = new Pm_TaskAllocation
+                    {
+                        OverTime = overTime,
+                        Status = newMainTaskStatus,
+                        Remark = remark
+                    };
+                }else
 
                 #endregion
 
                 _result.Msg = string.Format("操作成功!");
+                var logMsgChange = new StringBuilder();
+
+                var changeMsg = ChangeMsg(mainTaskInfoOld, mainTaskInfoNew);
+
+                _taskTextFileLogger.LogInformation("任务完成设置[成功],任务名称:{TaskName},操作者:{OperatorName}{ChangeMsg}", taskName, operatorName, changeMsg);
                 _result.Code = 0;
                 _sqlSugar.CommitTran();
 
@@ -934,7 +1076,7 @@ namespace OASystem.Infrastructure.Repositories.PersonnelModule
 
             _sqlSugar.BeginTran();
             var update1 = await _sqlSugar.Updateable<Pm_TaskRelevanceUser>()
-                                         .SetColumns(it => it.TaskStatus == TaskerEnum.UnFinished)
+                                         .SetColumns(it => it.TaskStatus == TaskEnum.UnFinished)
                                          .SetColumns(it => it.Cause == cause)
                                          .Where(it => it.Id == id)
                                          .ExecuteCommandAsync();
@@ -947,8 +1089,8 @@ namespace OASystem.Infrastructure.Repositories.PersonnelModule
 
             //设置任务状态
             var data2 = _sqlSugar.Queryable<Pm_TaskRelevanceUser>().Where(it => it.IsDel == 0 && it.TAId == _taId).ToList();
-            var data3 = data2.Where(it => it.TaskStatus == TaskerEnum.Finished && it.Id != id).ToList();
-            var data4 = data2.Where(it => it.TaskStatus == TaskerEnum.UnFinished && it.Id != id).ToList();
+            var data3 = data2.Where(it => it.TaskStatus == TaskEnum.Finished && it.Id != id).ToList();
+            var data4 = data2.Where(it => it.TaskStatus == TaskEnum.UnFinished && it.Id != id).ToList();
            
             if ((data2.Count - 1) == (data3.Count + data4.Count))
             {
@@ -987,7 +1129,7 @@ namespace OASystem.Infrastructure.Repositories.PersonnelModule
                 }
 
                 var data = await _sqlSugar.Queryable<Pm_TaskRelevanceUser>()
-                                          .Where(it => it.IsDel == 0 && it.Id == id && it.TaskStatus <= TaskerEnum.UnFinished)
+                                          .Where(it => it.IsDel == 0 && it.Id == id && it.TaskStatus <= TaskEnum.UnFinished)
                                           .ToListAsync();
                 if (data.Count > 0)
                 {
@@ -1051,7 +1193,7 @@ namespace OASystem.Infrastructure.Repositories.PersonnelModule
                     return _result;
                 }
 
-                if (data.TaskStatus != TaskerEnum.Finished)
+                if (data.TaskStatus != TaskEnum.Finished)
                 {
                     _result.Msg = string.Format("本任务尚未由发布人确认任务完成,不可评分!");
                     return _result;
@@ -1116,7 +1258,7 @@ namespace OASystem.Infrastructure.Repositories.PersonnelModule
                 return _result;
             }
             var subTaskUpdate = _sqlSugar.Updateable<Pm_TaskRelevanceUser>()
-                .SetColumns(it => it.TaskStatus == TaskerEnum.TaskStop)
+                .SetColumns(it => it.TaskStatus == TaskEnum.TaskStop)
                 .Where(it => it.TAId == taskId)
                 .ExecuteCommand();
 
@@ -1145,6 +1287,9 @@ namespace OASystem.Infrastructure.Repositories.PersonnelModule
                 return _result;
             }
             _sqlSugar.BeginTran();
+
+            var taskName = _sqlSugar.Queryable<Pm_TaskAllocation>().Where(it => it.IsDel == 0 && it.Id == taskId).Select(it => it.TaskName).First();
+            var operatorName = _sqlSugar.Queryable<Sys_Users>().Where(it => it.IsDel == 0 && it.Id == userId).Select(it => it.CnName).First();
             var nowStrig = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss");
             var taskUpdate = _sqlSugar.Updateable<Pm_TaskAllocation>()
                 .SetColumns(it => it.IsDel == 1)
@@ -1168,13 +1313,161 @@ namespace OASystem.Infrastructure.Repositories.PersonnelModule
             if (taskUpdate < 1)
             {
                 _result.Msg = "任务删除失败!";
+                _taskTextFileLogger.LogInformation("任务删除[失败],任务名称:{TaskName},操作者:{OperatorName}", taskName, operatorName);
                 _sqlSugar.RollbackTran();
                 return _result;
             }
             _result.Msg = "操作成功!";
+            _taskTextFileLogger.LogInformation("任务删除[成功],任务名称:{TaskName},操作者:{OperatorName}", taskName, operatorName);
             _result.Code = 0;
             _sqlSugar.CommitTran();
             return _result;
         }
+
+        #region 操作日志
+
+        /// <summary>
+        /// 记录任务分配步骤值改变
+        /// </summary>
+        /// <param name="before">操作前的步骤数据实体</param>
+        /// <param name="after">操作后的步骤数据实体</param>
+        /// <returns>表示同步操作的任务</returns>
+        /// <remarks>此方法会自动比较前后数据的差异,生成变更字段列表和操作描述</remarks>
+        public string ChangeMsg(Pm_TaskAllocation before, Pm_TaskAllocation after)
+        {
+            // 合并基础排除字段和额外排除字段
+            var allExcludedFields = GetDefaultExcludedFields();
+            var changedFields = GetChangeDetails(before, after, allExcludedFields);
+
+            if (!changedFields.Any()) return "\r\n无内容变更\r\n\r\n";
+
+            return "\r\n值改变内容(只记录有变化的信息):\r\n" + string.Join("\r\n", changedFields.Select(x =>
+                $"{x.FieldName} ({x.BeforeValue} -> {x.AfterValue});")) + "\r\n";
+
+        }
+
+        /// <summary>
+        /// 获取字段变更详情
+        /// </summary>
+        /// <param name="before">变更前</param>
+        /// <param name="after">变更后</param>
+        /// <param name="exclFields">排除字段</param>
+        /// <returns>变更详情列表</returns>
+        private List<FieldChangeDetail> GetChangeDetails(Pm_TaskAllocation before, Pm_TaskAllocation after, List<string> exclFields = null)
+        {
+            var changeDetails = new List<FieldChangeDetail>();
+            var defaultExclFields = GetDefaultExcludedFields();
+
+            // 合并排除字段
+            var allExclFields = defaultExclFields;
+            if (exclFields != null && exclFields.Any())
+            {
+                allExclFields = defaultExclFields.Union(exclFields).ToList();
+            }
+
+            if (before == null || after == null) return changeDetails;
+
+            var properties = typeof(Pm_TaskAllocation).GetProperties(BindingFlags.Public | BindingFlags.Instance);
+
+            foreach (var prop in properties)
+            {
+                // 跳过排除的字段
+                if (allExclFields.Contains(prop.Name))
+                {
+                    continue;
+                }
+
+                var beforeValue = prop.GetValue(before);
+                var afterValue = prop.GetValue(after);
+
+                // 处理字符串类型的特殊比较(忽略前后空格)
+                if (prop.PropertyType == typeof(string))
+                {
+                    var beforeString = beforeValue?.ToString()?.Trim();
+                    var afterString = afterValue?.ToString()?.Trim();
+
+                    if (beforeString != afterString)
+                    {
+                        changeDetails.Add(new FieldChangeDetail
+                        {
+                            FieldName = prop.Name,
+                            BeforeValue = FormatValue(beforeString),
+                            AfterValue = FormatValue(afterString)
+                        });
+                    }
+                }
+                else
+                {
+                    // 其他类型使用默认比较
+                    if (!Equals(beforeValue, afterValue))
+                    {
+                        changeDetails.Add(new FieldChangeDetail
+                        {
+                            FieldName = prop.Name,
+                            BeforeValue = FormatValue(beforeValue),
+                            AfterValue = FormatValue(afterValue)
+                        });
+                    }
+                }
+            }
+
+            return changeDetails;
+        }
+
+        /// <summary>
+        /// 格式化值显示
+        /// </summary>
+        /// <param name="value">原始值</param>
+        /// <returns>格式化后的值</returns>
+        private static string FormatValue(object value)
+        {
+            if (value == null) return "null";
+
+            var strValue = value.ToString();
+
+            // 处理空字符串
+            if (string.IsNullOrEmpty(strValue)) return "空";
+
+            // 处理布尔值
+            if (value is bool boolValue) return boolValue ? "是" : "否";
+
+            // 处理日期时间
+            if (value is DateTime dateTimeValue) return dateTimeValue.ToString("yyyy-MM-dd HH:mm");
+
+            // 处理枚举类型
+            if (value is Enum enumBool) return enumBool.GetDescription();
+
+            return strValue;
+        }
+
+        /// <summary>
+        /// 字段变更详情类
+        /// </summary>
+        private class FieldChangeDetail
+        {
+            public string FieldName { get; set; }
+            public string BeforeValue { get; set; }
+            public string AfterValue { get; set; }
+        }
+
+        /// <summary>
+        /// 获取默认排除的字段列表(包含系统字段和忽略字段)
+        /// </summary>
+        /// <returns>默认排除的字段列表</returns>
+        private static List<string> GetDefaultExcludedFields()
+        {
+            var defaultExcludedFields = new List<string>
+            {
+                nameof(Pm_TaskAllocation.Id),
+                nameof(Pm_TaskAllocation.CreateTime),
+                nameof(Pm_TaskAllocation.CreateUserId),
+                nameof(Pm_TaskAllocation.DeleteTime),
+                nameof(Pm_TaskAllocation.DeleteUserId)
+            };
+
+            return defaultExcludedFields.Distinct().ToList();
+        }
+
+        #endregion
     }
 }