Kaynağa Gözat

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

yuanrf 1 ay önce
ebeveyn
işleme
dc63431b95
21 değiştirilmiş dosya ile 1355 ekleme ve 972 silme
  1. 839 544
      OASystem/OASystem.Api/Controllers/GroupsController.cs
  2. 108 71
      OASystem/OASystem.Api/Middlewares/ExceptionHandlingMiddleware.cs
  3. 8 1
      OASystem/OASystem.Api/OAMethodLib/KiMiApi/KiMiApi.cs
  4. 7 0
      OASystem/OASystem.Api/Program.cs
  5. 1 6
      OASystem/OASystem.Domain/AesEncryption/EncryptionProcessor.cs
  6. 1 7
      OASystem/OASystem.Domain/Attributes/EncryptedAttribute.cs
  7. 1 6
      OASystem/OASystem.Domain/Dtos/Groups/InvertedListDto.cs
  8. 102 61
      OASystem/OASystem.Domain/Entities/Customer/Crm_DeleClient.cs
  9. 2 2
      OASystem/OASystem.Domain/Entities/Customer/Crm_VisaCustomerCompany.cs
  10. 33 1
      OASystem/OASystem.Domain/Entities/Customer/Crm_VisaCustomerFamily.cs
  11. 2 2
      OASystem/OASystem.Domain/Entities/Customer/Crm_VisaCustomerSchool.cs
  12. 61 8
      OASystem/OASystem.Domain/Entities/Groups/Grp_InvertedList.cs
  13. 4 0
      OASystem/OASystem.Domain/OASystem.Domain.csproj
  14. 30 4
      OASystem/OASystem.Domain/Result.cs
  15. 49 0
      OASystem/OASystem.Domain/ViewModels/Groups/InvertedListView.cs
  16. 3 1
      OASystem/OASystem.Domain/ViewModels/JsonView.cs
  17. 0 182
      OASystem/OASystem.Domain/ViewModels/VisaFormDetails/AusNewVisaApplicationForm.cs
  18. 19 29
      OASystem/OASystem.Infrastructure/Repositories/CRM/VisaDeleClientRepository.cs
  19. 36 13
      OASystem/OASystem.Infrastructure/Repositories/Groups/InvertedListRepository.cs
  20. 46 31
      OASystem/OASystem.Infrastructure/Repositories/Groups/ProcessOverviewRepository.cs
  21. 3 3
      OASystem/OASystem.Infrastructure/Repositories/PersonnelModule/TaskAllocationRepository.cs

Dosya farkı çok büyük olduğundan ihmal edildi
+ 839 - 544
OASystem/OASystem.Api/Controllers/GroupsController.cs


+ 108 - 71
OASystem/OASystem.Api/Middlewares/ExceptionHandlingMiddleware.cs

@@ -1,5 +1,7 @@
 
 using Microsoft.Data.SqlClient;
+using System.Text.Json;
+using System.Text.Json.Serialization;
 
 namespace OASystem.API.Middlewares
 {
@@ -43,86 +45,121 @@ namespace OASystem.API.Middlewares
         /// <summary>
         /// 自定义全局异常处理方法
         /// </summary>
-        /// <param name="context"></param>
-        /// <param name="exception"></param>
-        /// <param name="db"></param>
+        /// <param name="context">HTTP上下文</param>
+        /// <param name="exception">捕获的异常</param>
+        /// <param name="db">SqlSugar客户端</param>
         /// <returns></returns>
         private async Task HandleExceptionAsync(HttpContext context, Exception exception, SqlSugarClient db)
         {
-            //if (db.Ado != null && db.Ado.Transaction != null)
-            //{
-            //    try
-            //    {
-            //        db.Ado.RollbackTran();
-            //    }
-            //    catch (Exception ex)
-            //    {
-            //        _logger.LogError("Error rolling back transaction: {ErrorMessage}", ex.Message);
-            //    }
-            //}
-
-            // 检查响应是否已开始
-            if (!context.Response.HasStarted)
+            // ========== 1. 事务回滚(恢复并优化) ==========
+            try
             {
-                context.Response.ContentType = "application/json"; // 设置响应内容类型为 JSON
-                var response = context.Response;
-                var errorResponse = new JsonView
+                if (db?.Ado?.Transaction != null)
                 {
-                    Code = StatusCodes.Status500InternalServerError,
-                    Data = ""
-                };
-
-                // 根据异常类型设置不同的响应状态码和消息
-                switch (exception)
-                {
-                    case BusinessException businessEx: // 新增:处理 BusinessException
-                        response.StatusCode = StatusCodes.Status400BadRequest;
-                        errorResponse.Msg = businessEx.Message;
-                        errorResponse.Code = StatusCodes.Status400BadRequest; // 设置正确的 HTTP 状态码
-                        break;
-                    case SqlException sqlEx when sqlEx.Number == -2:
-                        response.StatusCode = StatusCodes.Status503ServiceUnavailable;
-                        errorResponse.Msg = "数据库连接超时,请稍后重试。";
-                        break;
-                    case SqlException sqlEx when sqlEx.Number == -4:
-                        response.StatusCode = StatusCodes.Status503ServiceUnavailable;
-                        errorResponse.Msg = "数据库连接池耗尽,请稍后重试。";
-                        break;
-                    case ApplicationException ex when ex.Message.Contains("Invalid token"):
-                        response.StatusCode = StatusCodes.Status403Forbidden;
-                        errorResponse.Msg = ex.Message;
-                        break;
-                    case ApplicationException ex:
-                        response.StatusCode = StatusCodes.Status400BadRequest;
-                        errorResponse.Msg = ex.Message;
-                        break;
-                    case KeyNotFoundException ex:
-                        response.StatusCode = StatusCodes.Status404NotFound;
-                        errorResponse.Msg = ex.Message;
-                        break;
-                    case SqlSugarException ex:
-                        response.StatusCode = ex.Message.Contains("timeout")
-                            ? StatusCodes.Status503ServiceUnavailable
-                            : StatusCodes.Status500InternalServerError;
-                        errorResponse.Msg = ex.Message.Contains("timeout")
-                            ? "数据库连接超时,请稍后重试。"
-                            : ex.Message;
-                        break;
-                    default:
-                        response.StatusCode = StatusCodes.Status400BadRequest;
-                        errorResponse.Msg = exception.Message; // 不直接暴露异常详细信息
-                        break;
+                    db.Ado.RollbackTran();
+                    _logger.LogWarning("Transaction rolled back due to exception: {ExceptionType}", exception.GetType().Name);
                 }
-
-                _logger.LogError(exception, "An exception occurred."); // 记录异常详细信息
-                var result = JsonConvert.SerializeObject(errorResponse);
-                await context.Response.WriteAsync(result); // 将错误响应写入客户端
             }
-            else
+            catch (Exception rollbackEx)
             {
-                // 如果响应已开始,记录日志但不做进一步处理
-                _logger.LogError(exception, "An exception occurred after response started.");
+                _logger.LogError(rollbackEx, "Failed to rollback transaction");
             }
+
+            // ========== 2. 响应已开始则仅记录日志 ==========
+            if (context.Response.HasStarted)
+            {
+                _logger.LogError(exception, "Exception occurred after response started | RequestId: {RequestId}",
+                    context.TraceIdentifier); // 记录请求ID
+                return;
+            }
+
+            // ========== 3. 构建标准化响应 ==========
+            context.Response.ContentType = "application/json; charset=utf-8";
+            var (statusCode, message, details, logLevel) = exception switch
+            {
+                // 业务异常:返回自定义信息,日志级别为Warning(非错误)
+                BusinessException businessEx => (
+                    businessEx.Code,
+                    businessEx.Msg,
+                    businessEx.Data,
+                    LogLevel.Warning
+                ),
+                // 权限/资源异常:标准化提示,日志Warning
+                UnauthorizedAccessException => (403, "无权访问此资源", null, LogLevel.Warning),
+                KeyNotFoundException => (404, "请求的资源不存在", null, LogLevel.Warning),
+                // 数据库超时:隐藏敏感信息,日志Error
+                SqlException sqlEx when IsDbTimeoutException(sqlEx) => (
+                    503,
+                    "数据库连接超时,请稍后重试。",
+                    null,
+                    LogLevel.Error
+                ),
+                SqlSugarException sugarEx when IsSugarTimeoutException(sugarEx) => (
+                    503,
+                    "数据库连接超时,请稍后重试。",
+                    null,
+                    LogLevel.Error
+                ),
+                // 其他数据库异常:隐藏原始消息,日志Error
+                SqlException => (500, "数据库服务异常", null, LogLevel.Error),
+                SqlSugarException => (500, "数据库服务异常", null, LogLevel.Error),
+                // 应用程序异常(业务逻辑错误):日志Warning
+                ApplicationException appEx => (400, appEx.Message, null, LogLevel.Warning),
+                // 兜底系统异常:隐藏原始消息,日志Critical
+                _ => (500, "服务器内部错误", null, LogLevel.Critical)
+            };
+
+            // ========== 4. 设置HTTP状态码(关键优化) ==========
+            context.Response.StatusCode = 200;
+
+            // ========== 5. 分级记录日志(含上下文) ==========
+            var logMessage = new Dictionary<string, string>
+            {
+                ["RequestId"] = context.TraceIdentifier,
+                ["Path"] = context.Request.Path,
+                ["Method"] = context.Request.Method,
+                ["User"] = context.User?.Identity?.Name ?? "Anonymous",
+                ["ExceptionType"] = exception.GetType().FullName
+            };
+            _logger.Log(logLevel, exception, "Global exception handled | {LogContext}",
+                System.Text.Json.JsonSerializer.Serialize(logMessage));
+
+            // ========== 6. 序列化响应(驼峰命名,隐藏空值) ==========
+            var jsonOptions = new JsonSerializerOptions
+            {
+                PropertyNamingPolicy = JsonNamingPolicy.CamelCase,
+                DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingNull
+            };
+            var result = System.Text.Json.JsonSerializer.Serialize(new JsonView
+            {
+                Code = statusCode,
+                Msg = message,
+                Data = details
+            }, jsonOptions);
+
+            await context.Response.WriteAsync(result);
+        }
+
+        // ========== 辅助方法:判断数据库超时异常(可扩展) ==========
+        private bool IsDbTimeoutException(SqlException sqlEx)
+        {
+            // 显式声明long数组,覆盖SQL Server/MySQL常见超时错误码
+            // 错误码说明:
+            // -2/-4:SQL Server 连接超时
+            // 1205:SQL Server 死锁
+            // 4060:SQL Server 无法连接数据库
+            // 2148732164:.NET 封装的数据库超时(对应0x80131904)
+            long[] timeoutErrorCodes = new long[] { -2, -4, 1205, 4060, 2148732164 };
+            // 转换sqlEx.Number为long后再判断(避免类型不匹配)
+            return timeoutErrorCodes.Contains((long)sqlEx.Number);
+        }
+
+        // ========== 辅助方法:判断SqlSugar超时异常 ==========
+        private bool IsSugarTimeoutException(SqlSugarException sugarEx)
+        {
+            var timeoutKeywords = new[] { "timeout", "超时", "deadlock", "死锁" };
+            return timeoutKeywords.Any(k => sugarEx.Message.Contains(k, StringComparison.OrdinalIgnoreCase));
         }
+
     }
 }

+ 8 - 1
OASystem/OASystem.Api/OAMethodLib/KiMiApi/KiMiApi.cs

@@ -100,6 +100,7 @@ namespace OASystem.API.OAMethodLib.KiMiApi
             return JsonConvert.DeserializeObject<KiMiRoot>(respStr);
         }
 
+
         private async Task<string> SeedAsync(List<SeedMessages> messages)
         {
             var completionRequest = new
@@ -110,7 +111,8 @@ namespace OASystem.API.OAMethodLib.KiMiApi
                     Role = StringEnumHelper.ToStringValue(x.Role),
                     x.Content
                 }),
-                temperature = 1
+                temperature = 1,
+                max_tokens = 4096
             };
 
             var completionJson = JsonConvert.SerializeObject(completionRequest);
@@ -126,6 +128,7 @@ namespace OASystem.API.OAMethodLib.KiMiApi
 
             return completionResponseContent;
         }
+
     }
 
     public class SeedMessages
@@ -148,9 +151,13 @@ namespace OASystem.API.OAMethodLib.KiMiApi
 
     public class Choice
     {
+        [JsonProperty("index")]
         public int Index { get; set; }
         public ReturnMessage Message { get; set; }
+
+        [JsonProperty("finish_reason")]
         public string FinishReason { get; set; }
+
     }
 
     public class Usage

+ 7 - 0
OASystem/OASystem.Api/Program.cs

@@ -558,6 +558,13 @@ builder.Services.TryAddSingleton(typeof(CommonService));
 
 var app = builder.Build();
 
+//// 1. 异常处理器应该在最早的位置(除了日志等)
+//app.UseExceptionHandler(new ExceptionHandlerOptions
+//{
+//    ExceptionHandlingPath = "/Home/Error", 
+//    AllowStatusCode404Response = true
+//});
+
 //自定义异常中间件
 app.UseMiddleware<ExceptionHandlingMiddleware>();
 

+ 1 - 6
OASystem/OASystem.Domain/AesEncryption/EncryptionProcessor.cs

@@ -1,10 +1,5 @@
 using OASystem.Domain.Attributes;
-using System;
-using System.Collections.Generic;
-using System.Linq;
 using System.Reflection;
-using System.Text;
-using System.Threading.Tasks;
 
 namespace OASystem.Domain.AesEncryption
 {
@@ -13,7 +8,7 @@ namespace OASystem.Domain.AesEncryption
     /// </summary>
     public static class EncryptionProcessor
     {
-       
+
         /// <summary>
         /// aes 加密
         /// </summary>

+ 1 - 7
OASystem/OASystem.Domain/Attributes/EncryptedAttribute.cs

@@ -1,10 +1,4 @@
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using System.Threading.Tasks;
-
-namespace OASystem.Domain.Attributes
+namespace OASystem.Domain.Attributes
 {
     /// <summary>
     /// Aes 加密/解密

+ 1 - 6
OASystem/OASystem.Domain/Dtos/Groups/InvertedListDto.cs

@@ -1,9 +1,4 @@
 using OASystem.Domain.ViewModels.Groups;
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using System.Threading.Tasks;
 
 namespace OASystem.Domain.Dtos.Groups
 {
@@ -48,7 +43,7 @@ namespace OASystem.Domain.Dtos.Groups
     public class InvertedListFileDownloadDto : PortDtoBase
     {
         /// <summary>
-        /// 请求类型
+        /// 团组Id
         /// </summary>
         public int DiId { get; set; }
     }

+ 102 - 61
OASystem/OASystem.Domain/Entities/Customer/Crm_DeleClient.cs

@@ -1,9 +1,4 @@
 using OASystem.Domain.Attributes;
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using System.Threading.Tasks;
 
 namespace OASystem.Domain.Entities.Customer
 {
@@ -196,17 +191,7 @@ namespace OASystem.Domain.Entities.Customer
         /// </summary>
         [SugarColumn(IsNullable = true, ColumnDataType = "Datetime")]
         public DateTime EndTime { get; set; }
-        /// <summary>
-        /// 申根是否在使馆有指纹记录 
-        /// 0否1是
-        /// </summary>
-        [SugarColumn(IsNullable = true, ColumnDataType = "int")]
-        public int IsFinger { get; set; } = 0;
-        /// <summary>
-        /// 申根指纹录入时间
-        /// </summary>
-        [SugarColumn(IsNullable = true, ColumnDataType = "DateTime")]
-        public DateTime FingerDate { get; set; }
+        
         /// <summary>
         /// 是否因公去过美国/加拿大
         /// 0否1是
@@ -233,33 +218,11 @@ namespace OASystem.Domain.Entities.Customer
         /// </summary>
         [SugarColumn(IsNullable = true, ColumnDataType = "int")]
         public int CanDays { get; set; } = 0;
-        /// <summary>
-        /// 是否曾获得过因公美国签证 0否1是
-        /// </summary>
-        [SugarColumn(IsNullable = true, ColumnDataType = "int")]
-        public int IsUSAVia { get; set; }
-        /// <summary>
-        /// 因公美国签证最近获得时间
-        /// 0否1是
-        /// </summary>
-        [SugarColumn(IsNullable = true, ColumnDataType = "DateTime")]
-        public DateTime GetUSAVisaDate { get; set; }
-        /// <summary>
         /// 因公美国签证地点
         /// </summary>
         [SugarColumn(IsNullable = true, ColumnDataType = "varchar(50)")]
         public string GetUPPlace { get; set; }
         /// <summary>
-        /// 因公美国签证种类
-        /// </summary>
-        [SugarColumn(IsNullable = true, ColumnDataType = "varchar(50)")]
-        public string USAVisaCate { get; set; }
-        /// <summary>
-        /// 因公美国签证编码
-        /// </summary>
-        [SugarColumn(IsNullable = true, ColumnDataType = "varchar(50)")]
-        public string USAVisaCode { get; set; }
-        /// <summary>
         /// 是否在使馆留过十指的指纹 0否1是
         /// </summary>
         [SugarColumn(IsNullable = true, ColumnDataType = "int")]
@@ -480,11 +443,46 @@ namespace OASystem.Domain.Entities.Customer
 
 
         //----------增加字段------------
+
         /// <summary>
-        /// 离婚原因
+        /// 赴美目的
         /// </summary>
-        [SugarColumn(IsNullable = true, ColumnDataType = "varchar(500)")]
-        public string DivorceRsn { get; set; }
+        [SugarColumn(IsNullable = true, ColumnDataType = "varchar(200)")]
+        public string USAPurpose { get; set; }
+
+        /// <summary>
+        /// 是否曾获得过因公美国签证 0否1是
+        /// </summary>
+        [SugarColumn(IsNullable = true, ColumnDataType = "int")]
+        public int IsUSAVia { get; set; }
+
+        /// <summary>
+        /// 因公美国签证最近获得时间 / 有效期
+        /// </summary>
+        [SugarColumn(IsNullable = true, ColumnDataType = "DateTime")]
+        public DateTime? GetUSAVisaDate { get; set; }
+        /// <summary>
+        /// 因公美国签证种类
+        /// </summary>
+        [SugarColumn(IsNullable = true, ColumnDataType = "varchar(50)")]
+        public string USAVisaCate { get; set; }
+        /// <summary>
+        /// 因公美国签证编码
+        /// </summary>
+        [SugarColumn(IsNullable = true, ColumnDataType = "varchar(50)")]
+        public string USAVisaCode { get; set; }
+
+        /// <summary>
+        /// 申根是否在使馆有指纹记录 
+        /// 0否1是
+        /// </summary>
+        [SugarColumn(IsNullable = true, ColumnDataType = "int")]
+        public int IsFinger { get; set; } = 0;
+        /// <summary>
+        /// 申根指纹录入时间
+        /// </summary>
+        [SugarColumn(IsNullable = true, ColumnDataType = "DateTime")]
+        public DateTime? FingerDate { get; set; }
 
         /// <summary>
         /// 美国驾照No
@@ -509,6 +507,24 @@ namespace OASystem.Domain.Entities.Customer
         [SugarColumn(IsNullable = true, ColumnDataType = "varchar(100)")]
         public string Resident { get; set; }
 
+        /// <summary>
+        /// 曾抵达过美国时间
+        /// </summary>
+        [SugarColumn(IsNullable = true, ColumnDataType = "varchar(50)")]
+        public string USAHadArrival‌ { get; set; }
+        /// <summary>
+        /// 曾停留美国天数
+        /// </summary>
+        [SugarColumn(IsNullable = true, ColumnDataType = "varchar(30)")]
+        public string USAHadDays‌ { get; set; }
+
+
+        /// <summary>
+        /// 离婚原因
+        /// </summary>
+        [SugarColumn(IsNullable = true, ColumnDataType = "varchar(500)")]
+        public string DivorceRsn { get; set; }
+
         /// <summary>
         /// 近五年内是否使用过任何社交账号
         /// </summary>
@@ -521,12 +537,6 @@ namespace OASystem.Domain.Entities.Customer
         [SugarColumn(IsNullable = true, ColumnDataType = "varchar(200)")]
         public string USAAddress { get; set; }
 
-        /// <summary>
-        /// 赴美目的
-        /// </summary>
-        [SugarColumn(IsNullable = true, ColumnDataType = "varchar(200)")]
-        public string USAPurpose { get; set; }
-
         /// <summary>
         /// 美国联系人或组织
         /// </summary>
@@ -583,16 +593,7 @@ namespace OASystem.Domain.Entities.Customer
         /// </summary>
         [SugarColumn(IsNullable = true, ColumnDataType = "varchar(300)")]
         public string DenyNationRsn { get; set; }
-        /// <summary>
-        /// 曾抵达过美国时间
-        /// </summary>
-        [SugarColumn(IsNullable = true, ColumnDataType = "varchar(50)")]
-        public string USAHadArrival‌ { get; set; }
-        /// <summary>
-        /// 曾停留美国天数
-        /// </summary>
-        [SugarColumn(IsNullable = true, ColumnDataType = "varchar(30)")]
-        public string USAHadDays‌ { get; set; }
+        
         /// <summary>
         /// 美国移民签证时间
         /// </summary>
@@ -662,7 +663,7 @@ namespace OASystem.Domain.Entities.Customer
         /// <summary>
         /// 母亲出生日期
         /// </summary>
-        [SugarColumn( IsNullable = true, ColumnDataType = "varchar(50)")]
+        [SugarColumn(IsNullable = true, ColumnDataType = "varchar(50)")]
         public DateTime? MthBirth { get; set; }
     }
 
@@ -715,7 +716,10 @@ namespace OASystem.Domain.Entities.Customer
     {
         public string Country { get; set; }
 
-        public DateTime Date { get; set; }
+        public DateTime? Date { get; set; }
+        public string Address { get; set; }
+
+        public string VisaType { get; set; }
 
         public string Reason { get; set; }
     }
@@ -727,9 +731,9 @@ namespace OASystem.Domain.Entities.Customer
     {
         public string Country { get; set; }
 
-        public DateTime ArrivalDate { get; set; }
+        public DateTime? ArrivalDate { get; set; }
 
-        public DateTime DepartureDate { get; set; }
+        public DateTime? DepartureDate { get; set; }
 
         public string VisaType { get; set; }
     }
@@ -743,4 +747,41 @@ namespace OASystem.Domain.Entities.Customer
 
         public string VisitDate { get; set; }
     }
+
+    /// <summary>
+    /// 定义申根签证记录类
+    /// </summary>
+    public class SchengenVisaRecord
+    {
+        public string VisaType { get; set; }        // 签证类型
+        public string VisaNumber { get; set; }      // 签证号码
+        public DateTime? IssueDate { get; set; }     // 签发日期
+        public DateTime? ExpiryDate { get; set; }    // 有效期至
+        //public string IssuingCountry { get; set; }  // 签发国家
+    }
+
+    /// <summary>
+    /// 定义社交账号类
+    /// </summary>
+    public class SocialAccount
+    {
+        public string Platform { get; set; }       // 平台名称
+        public string Account { get; set; }    // 账号
+    }
+
+    /// <summary>
+    /// 亲属朋友信息
+    /// </summary>
+    public class PersonInfo
+    {
+        /// <summary>
+        /// 类型(亲属/朋友/联系人)
+        /// </summary>
+        public string Type { get; set; }
+        public string Name { get; set; }       // 姓名
+        public DateTime? BirthDay { get; set; }
+        public string Address { get; set; }   // 地址
+        public string ContactInfo { get; set; } // 联系方式
+    }
+
 }

+ 2 - 2
OASystem/OASystem.Domain/Entities/Customer/Crm_VisaCustomerCompany.cs

@@ -46,12 +46,12 @@ namespace OASystem.Domain.Entities.Customer
         /// 雇佣起始年月日
         /// </summary>
         [SugarColumn(IsNullable = true, ColumnDataType = "DateTime")]
-        public DateTime WorkStart { get; set; }
+        public DateTime? WorkStart { get; set; }
         /// <summary>
         /// 雇佣结束年月日
         /// </summary>
         [SugarColumn(IsNullable = true, ColumnDataType = "DateTime")]
-        public DateTime WorkEnd { get; set; }
+        public DateTime? WorkEnd { get; set; }
         /// <summary>
         /// 工作职责及内容简述
         /// </summary>

+ 33 - 1
OASystem/OASystem.Domain/Entities/Customer/Crm_VisaCustomerFamily.cs

@@ -29,7 +29,7 @@ namespace OASystem.Domain.Entities.Customer
         /// 家庭成员出生日期
         /// </summary>
         [SugarColumn(IsNullable =true,ColumnDataType ="DateTime")]
-        public DateTime BirthDay { get; set; }
+        public DateTime? BirthDay { get; set; }
         /// <summary>
         /// 家庭成员出生地
         /// </summary>
@@ -85,5 +85,37 @@ namespace OASystem.Domain.Entities.Customer
         /// </summary>
         [SugarColumn(IsNullable = true, ColumnDataType = "int")]
         public int IsUSA { get; set; }
+
+        /* 新增字段 */
+        /// <summary>
+        /// 婚姻状态
+        /// </summary>
+        [SugarColumn(IsNullable = true, ColumnDataType = "varchar(50)")]
+        public string MaritalStatus { get; set; }
+
+        /// <summary>
+        /// 现国籍
+        /// </summary>
+        [SugarColumn(IsNullable = true, ColumnDataType = "varchar(50)")]
+        public string CurrentNationality { get; set; }
+
+        /// <summary>
+        /// 出生国
+        /// </summary>
+        [SugarColumn(IsNullable = true, ColumnDataType = "varchar(50)")]
+        public string CountryOfBirth { get; set; }
+
+        /// <summary>
+        /// 现居住国
+        /// </summary>
+        [SugarColumn(IsNullable = true, ColumnDataType = "varchar(50)")]
+        public string CurrentResidenceCountry { get; set; }
+
+        /// <summary>
+        /// 现职务
+        /// </summary>
+        [SugarColumn(IsNullable = true, ColumnDataType = "varchar(50)")]
+        public string CurrentOccupation { get; set; }
+
     }
 }

+ 2 - 2
OASystem/OASystem.Domain/Entities/Customer/Crm_VisaCustomerSchool.cs

@@ -47,11 +47,11 @@ namespace OASystem.Domain.Entities.Customer
         /// 就读起始日
         /// </summary>
         [SugarColumn(IsNullable = true, ColumnDataType = "DateTime")]
-        public DateTime StudyStart { get; set; }
+        public DateTime? StudyStart { get; set; }
         /// <summary>
         /// 就读结束日
         /// </summary>
         [SugarColumn(IsNullable = true, ColumnDataType = "DateTime")]
-        public DateTime StudyEnd { get; set; }
+        public DateTime? StudyEnd { get; set; }
     }
 }

+ 61 - 8
OASystem/OASystem.Domain/Entities/Groups/Grp_InvertedList.cs

@@ -1,10 +1,4 @@
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using System.Threading.Tasks;
-
-namespace OASystem.Domain.Entities.Groups
+namespace OASystem.Domain.Entities.Groups
 {
     /// <summary>
     /// 团组倒推表
@@ -26,6 +20,12 @@ namespace OASystem.Domain.Entities.Groups
         [SugarColumn(IsNullable = true, ColumnDataType = "varchar(30)")]
         public string ApprovalDataDt { get; set; }
 
+        /// <summary>
+        /// 报批资料准备时间(客户) - A
+        /// </summary>
+        [SugarColumn(IsNullable = true, ColumnDataType = "varchar(30)")]
+        public string Client_ApprovalDataDt { get; set; }
+
         /// <summary>
         /// 报批资料准备
         /// 是否完成
@@ -46,6 +46,12 @@ namespace OASystem.Domain.Entities.Groups
         [SugarColumn(IsNullable = true, ColumnDataType = "varchar(30)")]
         public string ApprovalDt { get; set; }
 
+        /// <summary>
+        /// 报批时间(客户) - A
+        /// </summary>
+        [SugarColumn(IsNullable = true, ColumnDataType = "varchar(30)")]
+        public string Client_ApprovalDt { get; set; }
+
         /// <summary>
         /// 报批时间
         /// 1 预批件 2 正常批件 默认值??-1
@@ -73,6 +79,12 @@ namespace OASystem.Domain.Entities.Groups
         [SugarColumn(IsNullable = true, ColumnDataType = "varchar(30)")]
         public string IssueApprovalDt { get; set; }
 
+        /// <summary>
+        /// 出批件时间(客户) - A
+        /// </summary>
+        [SugarColumn(IsNullable = true, ColumnDataType = "varchar(30)")]
+        public string Client_IssueApprovalDt { get; set; }
+
         /// <summary>
         /// 出批件
         /// 是否完成
@@ -116,6 +128,12 @@ namespace OASystem.Domain.Entities.Groups
         [SugarColumn(IsNullable = true, ColumnDataType = "varchar(30)")]
         public string VisaInformationDt { get; set; }
 
+        /// <summary>
+        /// 签证资料准备时间(客户) - A
+        /// </summary>
+        [SugarColumn(IsNullable = true, ColumnDataType = "varchar(30)")]
+        public string Client_VisaInformationDt { get; set; }
+
         /// <summary>
         /// 签证资料准备
         /// 是否完成
@@ -136,6 +154,12 @@ namespace OASystem.Domain.Entities.Groups
         [SugarColumn(IsNullable = true, ColumnDataType = "varchar(30)")]
         public string SendVisaDt { get; set; }
 
+        /// <summary>
+        /// 送签时间(客户) - B
+        /// </summary>
+        [SugarColumn(IsNullable = true, ColumnDataType = "varchar(30)")]
+        public string Client_SendVisaDt { get; set; }
+
         /// <summary>
         /// 送签
         /// 是否完成
@@ -156,6 +180,12 @@ namespace OASystem.Domain.Entities.Groups
         [SugarColumn(IsNullable = true, ColumnDataType = "varchar(30)")]
         public string IssueVisaDt { get; set; }
 
+        /// <summary>
+        /// 出签时间(客户) - B
+        /// </summary>
+        [SugarColumn(IsNullable = true, ColumnDataType = "varchar(30)")]
+        public string Client_IssueVisaDt { get; set; }
+
         /// <summary>
         /// 出签
         /// 是否完成
@@ -170,13 +200,18 @@ namespace OASystem.Domain.Entities.Groups
         [SugarColumn(IsNullable = true, ColumnDataType = "varchar(300)")]
         public string IssueVisaRemark { get; set; } = "外办领取签证";
 
-
         /// <summary>
         /// 机票 - B
         /// </summary>
         [SugarColumn(IsNullable = true, ColumnDataType = "varchar(30)")]
         public string AirTicketDt { get; set; }
 
+        /// <summary>
+        /// 机票(客户) - B
+        /// </summary>
+        [SugarColumn(IsNullable = true, ColumnDataType = "varchar(30)")]
+        public string Client_AirTicketDt { get; set; }
+
         /// <summary>
         /// 机票
         /// 是否完成
@@ -197,6 +232,12 @@ namespace OASystem.Domain.Entities.Groups
         [SugarColumn(IsNullable = true, ColumnDataType = "varchar(30)")]
         public string HotelDt { get; set; }
 
+        /// <summary>
+        /// 酒店(客户) - B
+        /// </summary>
+        [SugarColumn(IsNullable = true, ColumnDataType = "varchar(30)")]
+        public string Client_HotelDt { get; set; }
+
         /// <summary>
         /// 酒店
         /// 是否完成
@@ -217,6 +258,12 @@ namespace OASystem.Domain.Entities.Groups
         [SugarColumn(IsNullable = true, ColumnDataType = "varchar(30)")]
         public string PreTripMeetingDt { get; set; }
 
+        /// <summary>
+        /// 行前会(客户) - A
+        /// </summary>
+        [SugarColumn(IsNullable = true, ColumnDataType = "varchar(30)")]
+        public string Client_PreTripMeetingDt { get; set; }
+
         /// <summary>
         /// 行前会
         /// 是否完成
@@ -237,6 +284,12 @@ namespace OASystem.Domain.Entities.Groups
         [SugarColumn(IsNullable = true, ColumnDataType = "varchar(30)")]
         public string AirportdDropOffDt { get; set; }
 
+        /// <summary>
+        /// 送机(客户) - A
+        /// </summary>
+        [SugarColumn(IsNullable = true, ColumnDataType = "varchar(30)")]
+        public string Client_AirportdDropOffDt { get; set; }
+
         /// <summary>
         /// 送机
         /// 是否完成

+ 4 - 0
OASystem/OASystem.Domain/OASystem.Domain.csproj

@@ -31,4 +31,8 @@
     <PackageReference Include="SqlSugarCore" Version="5.1.3.32" />
   </ItemGroup>
 
+  <ItemGroup>
+    <Folder Include="ViewModels\VisaFormDetails\" />
+  </ItemGroup>
+
 </Project>

+ 30 - 4
OASystem/OASystem.Domain/Result.cs

@@ -1,4 +1,6 @@
-namespace OASystem.Domain
+using System.Runtime.Serialization;
+
+namespace OASystem.Domain
 {
     public class Result
     {
@@ -21,9 +23,11 @@
         }
     }
 
+
     /// <summary>
     /// 业务异常基类
     /// </summary>
+    [Serializable] // 核心:添加序列化特性(IIS识别的关键)
     public class BusinessException : Exception
     {
         /// <summary>
@@ -31,17 +35,19 @@
         /// </summary>
         public int Code { get; set; }
 
-
         /// <summary>
         /// 错误消息
         /// </summary>
-        public string Msg{ get; set; }
+        public string Msg { get; set; }
 
         /// <summary>
         /// 错误详情
         /// </summary>
         public new object Data { get; set; }
 
+        // 无参构造函数(序列化必备,即使不直接使用)
+        public BusinessException() : base() { }
+
         public BusinessException(string message) : base(message)
         {
             Code = 400;
@@ -69,11 +75,31 @@
         }
 
         public BusinessException(string message, Exception innerException)
-        : base(message, innerException)
+            : base(message, innerException)
         {
             Code = 400;
             Msg = message;
         }
+
+        // 核心:序列化构造函数(IIS反序列化时必须调用)
+        protected BusinessException(SerializationInfo info, StreamingContext context)
+            : base(info, context)
+        {
+            // 读取序列化的自定义属性(和GetObjectData对应)
+            Code = info.GetInt32(nameof(Code));
+            Msg = info.GetString(nameof(Msg));
+            Data = info.GetValue(nameof(Data), typeof(object));
+        }
+
+        // 核心:重写GetObjectData(序列化自定义属性)
+        public override void GetObjectData(SerializationInfo info, StreamingContext context)
+        {
+            base.GetObjectData(info, context);
+            // 写入自定义属性到序列化流
+            info.AddValue(nameof(Code), Code);
+            info.AddValue(nameof(Msg), Msg);
+            info.AddValue(nameof(Data), Data);
+        }
     }
 
 

+ 49 - 0
OASystem/OASystem.Domain/ViewModels/Groups/InvertedListView.cs

@@ -281,6 +281,55 @@ namespace OASystem.Domain.ViewModels.Groups
         public bool IsSelectedAirportdDropOff { get; set; } = true;
         #endregion
 
+        #region 新增每项客户使用使用时间
+        /// <summary>
+        /// 报批资料准备时间(客户) - A
+        /// </summary>
+        public string Client_ApprovalDataDt { get; set; }
+
+        /// <summary>
+        /// 报批时间(客户) - A
+        /// </summary>
+        public string Client_ApprovalDt { get; set; }
+
+        /// <summary>
+        /// 出批件时间(客户) - A
+        /// </summary>
+        public string Client_IssueApprovalDt { get; set; }
+
+        /// <summary>
+        /// 签证资料准备时间(客户) - A
+        /// </summary>
+        public string Client_VisaInformationDt { get; set; }
+
+        /// <summary>
+        /// 送签时间(客户) - B
+        /// </summary>
+        public string Client_SendVisaDt { get; set; }
+
+        /// <summary>
+        /// 出签时间(客户) - B
+        /// </summary>
+        public string Client_IssueVisaDt { get; set; }
+
+        /// <summary>
+        /// 机票(客户) - B
+        /// </summary>
+        public string Client_AirTicketDt { get; set; }
+        /// <summary>
+        /// 酒店(客户) - B
+        /// </summary>
+        public string Client_HotelDt { get; set; }
+        /// <summary>
+        /// 行前会(客户) - A
+        /// </summary>
+        public string Client_PreTripMeetingDt { get; set; }
+
+        /// <summary>
+        /// 送机(客户) - A
+        /// </summary>
+        public string Client_AirportdDropOffDt { get; set; }
+        #endregion
     }
     /// <summary>
     /// 签证国家信息

+ 3 - 1
OASystem/OASystem.Domain/ViewModels/JsonView.cs

@@ -1,4 +1,6 @@
-namespace OASystem.Domain.ViewModels;
+using System.Text.Json.Serialization;
+
+namespace OASystem.Domain.ViewModels;
 
 /// <summary>
 /// 统一返回结构

+ 0 - 182
OASystem/OASystem.Domain/ViewModels/VisaFormDetails/AusNewVisaApplicationForm.cs

@@ -1,182 +0,0 @@
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using System.Threading.Tasks;
-
-namespace OASystem.Domain.ViewModels.VisaFormDetails
-{
-    /// <summary>
-    /// 澳大利亚新签证申请表
-    /// </summary>
-    public class AusNewVisaApplicationForm
-    {
-        // 是否曾经去过其他国家
-        ///<summary>是否曾经去过其他国家</summary>
-        public List<CountryVisit> CountryVisits { get; set; }
-
-        // 申请人的个人信息
-        ///<summary>姓名</summary>
-        public string Name { get; set; }
-        ///<summary>曾用名</summary>
-        public string Alias { get; set; }
-        ///<summary>婚姻状况</summary>
-        public string MaritalStatus { get; set; }
-        ///<summary>出生地</summary>
-        public string BirthPlace { get; set; }
-        ///<summary>性别</summary>
-        public string Gender { get; set; }
-        ///<summary>手机</summary>
-        public string Mobile { get; set; }
-        ///<summary>出生日期</summary>
-        public string BirthDate { get; set; }
-        ///<summary>现在住址</summary>
-        public string CurrentAddress { get; set; }
-
-        ///<summary>在职人员信息</summary>
-        public EmploymentInfo EmploymentInfo { get; set; }
-
-        ///<summary>申请人家庭成员</summary>
-        public List<FamilyMember> FamilyMembers { get; set; }
-
-        ///<summary>关系信息</summary>
-        public List<Relation> Relations { get; set; }
-
-        ///<summary>拒签历史</summary>
-        public List<Rejection> Rejections { get; set; }
-
-        ///<summary>新西兰/澳大利亚旅行历史</summary>
-        public List<TravelHistory> TravelHistories { get; set; }
-
-        ///<summary>教育经历</summary>
-        public List<Education> Educations { get; set; }
-
-        ///<summary>工作经历</summary>
-        public List<WorkExperience> WorkExperiences { get; set; }
-
-        ///<summary>服兵役历史</summary>
-        public List<MilitaryService> MilitaryServices { get; set; }
-
-    }
-
-    public class CountryVisit
-    {
-        ///<summary>国家</summary>
-        public string Country { get; set; }
-        ///<summary>访问日期</summary>
-        public string VisitDate { get; set; }
-    }
-
-    public class TravelHistory
-    {
-        public int Order { get; set; } // 次序
-        public string ArrivalDate { get; set; }   // 抵达日期
-        public string DepartureDate { get; set; } // 离开日期
-    }
-
-    public class EmploymentInfo
-    {
-        ///<summary>现单位名称</summary>
-        public string CompanyName { get; set; }
-        ///<summary>现单位地址</summary>
-        public string CompanyAddress { get; set; }
-        ///<summary>单位电话</summary>
-        public string CompanyPhone { get; set; }
-        ///<summary>目前职位</summary>
-        public string Position { get; set; }
-        ///<summary>月收入</summary>
-        public decimal MonthlyIncome { get; set; }
-        ///<summary>赴新费用</summary>
-        public string TravelCostType { get; set; }
-        ///<summary>负责人姓名</summary>
-        public string ResponsiblePersonName { get; set; }
-        ///<summary>负责人电话</summary>
-        public string ResponsiblePersonPhone { get; set; }
-    }
-
-    public class FamilyMember
-    {
-        ///<summary>关系</summary>
-        public string Relation { get; set; }
-        ///<summary>姓名</summary>
-        public string Name { get; set; }
-        ///<summary>出生日期</summary>
-        public string BirthDate { get; set; }
-        ///<summary>婚姻状况</summary>
-        public string MaritalStatus { get; set; }
-        ///<summary>现国籍</summary>
-        public string CurrentNationality { get; set; }
-        ///<summary>出生国</summary>
-        public string BirthCountry { get; set; }
-        ///<summary>居住国</summary>
-        public string CesidenceCountry { get; set; }
-        ///<summary>现职务</summary>
-        public string CurrentPosition { get; set; }
-    }
-
-    public class Relation
-    {
-        ///<summary>关系类型</summary>
-        public string RelationType { get; set; }
-        ///<summary>姓名</summary>
-        public string Name { get; set; }
-        ///<summary>出生日期</summary>
-        public string BirthDate { get; set; }
-        ///<summary>地址</summary>
-        public string Address { get; set; }
-        ///<summary>联系方式</summary>
-        public string Contact { get; set; }
-    }
-
-    public class Rejection
-    {
-        ///<summary>国家</summary>
-        public string Country { get; set; }
-        ///<summary>申请日期</summary>
-        public string ApplicationDate { get; set; }
-        ///<summary>申请地点</summary>
-        public string ApplicationLocation { get; set; }
-        ///<summary>申请签证类别</summary>
-        public string VisaCategory { get; set; }
-        ///<summary>拒签原因</summary>
-        public string Reason { get; set; }
-    }
-
-    public class Education
-    {
-        ///<summary>院校名称</summary>
-        public string SchoolName { get; set; }
-        ///<summary>入学时间</summary>
-        public string EnrollmentDate { get; set; }
-        ///<summary>毕业时间</summary>
-        public string GraduationDate { get; set; }
-        ///<summary>课程专业名称</summary>
-        public string Major { get; set; }
-    }
-
-    public class WorkExperience
-    {
-        ///<summary>单位名称</summary>
-        public string CompanyName { get; set; }
-        ///<summary>开始时间</summary>
-        public string StartDate { get; set; }
-        ///<summary>结束时间</summary>
-        public string EndDate { get; set; }
-        ///<summary>单位所在地</summary>
-        public string Location { get; set; }
-        ///<summary>职务</summary>
-        public string Position { get; set; }
-    }
-
-    public class MilitaryService
-    {
-        ///<summary>军衔</summary>
-        public string Rank { get; set; }
-        ///<summary>所属部队</summary>
-        public string Unit { get; set; }
-        ///<summary>军种</summary>
-        public string Branch { get; set; }
-        ///<summary>服役时间</summary>
-        public string ServiceDate { get; set; }
-    }
-}

+ 19 - 29
OASystem/OASystem.Infrastructure/Repositories/CRM/VisaDeleClientRepository.cs

@@ -1,22 +1,13 @@
 
 using AutoMapper;
-using Newtonsoft.Json;
 using OASystem.Domain;
 using OASystem.Domain.AesEncryption;
 using OASystem.Domain.Dtos;
 using OASystem.Domain.Dtos.CRM;
 using OASystem.Domain.Dtos.UserDto;
 using OASystem.Domain.Entities.Customer;
-using OASystem.Domain.Entities.Groups;
-using OASystem.Domain.Entities.Resource;
 using OASystem.Domain.ViewModels.CRM;
-using OASystem.Domain.ViewModels.Groups;
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Runtime.Intrinsics.X86;
-using System.Text;
-using System.Threading.Tasks;
+using System.Reflection;
 
 namespace OASystem.Infrastructure.Repositories.CRM
 {
@@ -27,11 +18,11 @@ namespace OASystem.Infrastructure.Repositories.CRM
     {
         private readonly IMapper _mapper;
         private readonly JsonView _jv = new() { Code = StatusCodes.Status400BadRequest, Msg = "操作失败!" };
-        public VisaDeleClientRepository(SqlSugarClient sqlSugar,IMapper mapper) :
+        public VisaDeleClientRepository(SqlSugarClient sqlSugar, IMapper mapper) :
             base(sqlSugar)
         {
             this._mapper = mapper;
-           
+
         }
 
         /// <summary>
@@ -42,7 +33,7 @@ namespace OASystem.Infrastructure.Repositories.CRM
         public async Task<Result> GetCrmList(DtoBase dto)
         {
             Result result = new Result() { Code = -2 };
-            if (dto.PortType == 1 || dto.PortType == 2 || dto.PortType == 3) 
+            if (dto.PortType == 1 || dto.PortType == 2 || dto.PortType == 3)
             {
                 string sql = string.Format(@"Select cdc.Id,cdc.LastName,cdc.FirstName,ccc.CompanyFullName,Sex,Marriage,
                                              	    Phone LandlinePhone,Tel,crmCard1.CertNo IDNo,crmCard2.CertNo PassportNo
@@ -94,7 +85,7 @@ namespace OASystem.Infrastructure.Repositories.CRM
         {
             int addId = -1;
 
-            
+
 
 
             return addId;
@@ -112,7 +103,7 @@ namespace OASystem.Infrastructure.Repositories.CRM
             string clientSql = string.Format(@"Select * From Crm_DeleClient Where LastName+FirstName='{0}' And Sex = {1}",
                                              client.ClientName, client.Sex);
             var clientInfo = await _sqlSugar.SqlQueryable<VisaDeleClientListView>(clientSql).FirstAsync();
-            if(clientInfo == null) return false;
+            if (clientInfo == null) return false;
 
             string cardSql = string.Format(@"Select * From Crm_CustomerCert Where SdId=773 And DcId={0}", clientInfo.Id);
             var cardInfo = await _sqlSugar.SqlQueryable<CustomerCertView>(cardSql).FirstAsync();
@@ -151,23 +142,23 @@ namespace OASystem.Infrastructure.Repositories.CRM
                 if (cerdStatus > 0) return true;
             }
 
-            
+
             return false;
         }
 
         public async Task<Result> OpCustomer(DeleClientOpDto dto)
         {
-           Result result = new Result() { Code = -2, Msg = "未知错误" };
+            Result result = new Result() { Code = -2, Msg = "未知错误" };
             try
             {
                 EncryptionProcessor.EncryptProperties(dto.DeleClient);
 
                 BeginTran();
                 int deleId = 0;
-                if (dto.Status==1)//添加
+                if (dto.Status == 1)//添加
                 {
                     string selectSql = string.Format(@"select * from Crm_DeleClient where  LastName+FirstName='{0}' and Phone='{1}' and IsDel='{2}'"
-                                                      , dto.DeleClient.LastName+dto.DeleClient.FirstName, dto.DeleClient.Phone, 0);
+                                                      , dto.DeleClient.LastName + dto.DeleClient.FirstName, dto.DeleClient.Phone, 0);
                     var DeleClient = await _sqlSugar.SqlQueryable<Crm_DeleClient>(selectSql).FirstAsync();//查询是否存在
                     if (DeleClient != null)
                     {
@@ -185,12 +176,12 @@ namespace OASystem.Infrastructure.Repositories.CRM
                         }
                         result = new Result() { Code = 0, Msg = "添加成功!" };
                         deleId = id;
-                        
+
                     }
                 }
                 else if (dto.Status == 2)//修改
                 {
-                    deleId=dto.DeleClient.Id;
+                    deleId = dto.DeleClient.Id;
 
                     DateTime? dateTime = null;
                     bool isDt = DateTime.TryParse(dto.DeleClient.BirthDay, out DateTime dt);
@@ -297,7 +288,7 @@ namespace OASystem.Infrastructure.Repositories.CRM
                         result = new Result() { Code = -1, Msg = "修改失败!" };
                     }
                     result = new Result() { Code = 0, Msg = "修改成功!" };
-                    
+
                 }
                 //进行其他表
                 if (result.Code == 0)
@@ -326,7 +317,7 @@ namespace OASystem.Infrastructure.Repositories.CRM
                                 IsUSA = Crm_VisaCustomerFamily.IsUSA,
                                 Remark = Crm_VisaCustomerFamily.Remark,
                             }).ExecuteCommandAsync();
-                            if (res==0)
+                            if (res == 0)
                             {
                                 result = new Result() { Code = -1, Msg = "家庭成员信息保存失败!" };
                                 RollbackTran();
@@ -334,7 +325,7 @@ namespace OASystem.Infrastructure.Repositories.CRM
                         }
                         else if (item.Id == 0)//添加
                         {
-                           int sss= await _sqlSugar.Insertable(Crm_VisaCustomerFamily).ExecuteReturnIdentityAsync();
+                            int sss = await _sqlSugar.Insertable(Crm_VisaCustomerFamily).ExecuteReturnIdentityAsync();
                             if (sss == 0)
                             {
                                 result = new Result() { Code = -1, Msg = "家庭成员信息保存失败!" };
@@ -352,7 +343,7 @@ namespace OASystem.Infrastructure.Repositories.CRM
                         {
                             int res = await _sqlSugar.Updateable<Crm_CustomerCert>().Where(a => a.Id == CustomerCert.Id).SetColumns(a => new Crm_CustomerCert
                             {
-                                DcId=CustomerCert.DcId,
+                                DcId = CustomerCert.DcId,
                                 SdId = CustomerCert.SdId,
                                 CertNo = CustomerCert.CertNo,
                                 Country = CustomerCert.Country,
@@ -389,7 +380,7 @@ namespace OASystem.Infrastructure.Repositories.CRM
                         {
                             int res = await _sqlSugar.Updateable<Crm_VisaCustomerCompany>().Where(a => a.Id == VisaCustomerCompany.Id).SetColumns(a => new Crm_VisaCustomerCompany
                             {
-                                DcId=VisaCustomerCompany.DcId,
+                                DcId = VisaCustomerCompany.DcId,
                                 Company = VisaCustomerCompany.Company,
                                 CompanyAddress = VisaCustomerCompany.CompanyAddress,
                                 Phone = VisaCustomerCompany.Phone,
@@ -469,11 +460,11 @@ namespace OASystem.Infrastructure.Repositories.CRM
             Result result = new Result() { Code = -2, Msg = "未知错误" };
             try
             {
-                bool isOk=await SoftDeleteByIdAsync<Crm_DeleClient>(dto.Id.ToString(),dto.DeleteUserId);
+                bool isOk = await SoftDeleteByIdAsync<Crm_DeleClient>(dto.Id.ToString(), dto.DeleteUserId);
                 if (isOk)//删除其他表数据
                 {
                     //客户工作经历
-                    await _sqlSugar.Updateable<Crm_VisaCustomerCompany>().Where(a => a.DcId==dto.Id).SetColumns(a => new Crm_VisaCustomerCompany()
+                    await _sqlSugar.Updateable<Crm_VisaCustomerCompany>().Where(a => a.DcId == dto.Id).SetColumns(a => new Crm_VisaCustomerCompany()
                     {
                         IsDel = 1,
                         DeleteUserId = dto.DeleteUserId,
@@ -511,7 +502,6 @@ namespace OASystem.Infrastructure.Repositories.CRM
             return result;
         }
 
-
         #region 签证客户资料 New 2025-06-04
 
 

+ 36 - 13
OASystem/OASystem.Infrastructure/Repositories/Groups/InvertedListRepository.cs

@@ -35,7 +35,7 @@ namespace OASystem.Infrastructure.Repositories.Groups
         /// 基础数据
         /// </summary>
         /// <returns></returns>
-        public async Task<Result> _Init()
+        public async Task<Result> Init()
         {
             dynamic groupData = null;
             var groupData1 = await _delegationInfoRep.PostShareGroupInfos(1);
@@ -65,7 +65,7 @@ namespace OASystem.Infrastructure.Repositories.Groups
         /// Info
         /// </summary>
         /// <returns></returns>
-        public async Task<Result> _Info(int portTypeId,int diId)
+        public async Task<Result> Info(int portTypeId,int diId)
         {
             #region 参数验证
             if (portTypeId < 1)
@@ -116,7 +116,6 @@ namespace OASystem.Infrastructure.Repositories.Groups
                 string countryDesc = "";
                 foreach (var item in visitCountry)
                 {
-
                     int visaDays = Convert.ToInt32(visaFeeDatas.Find(it => it.VisaCountry.Equals(item.Trim()))?.VisaTime ?? "0");
                     visaCountryInfos.Add(new VisaCountryInfo()
                     {
@@ -152,6 +151,21 @@ namespace OASystem.Infrastructure.Repositories.Groups
 
             int ilId = info.Id;
 
+            #region 新增客户时间字段值不存在使用默认值
+
+            if (string.IsNullOrEmpty(info.Client_ApprovalDataDt)) info.Client_ApprovalDataDt = info.ApprovalDataDt;
+            if (string.IsNullOrEmpty(info.Client_ApprovalDt)) info.Client_ApprovalDt = info.ApprovalDt;
+            if (string.IsNullOrEmpty(info.Client_IssueApprovalDt)) info.Client_IssueApprovalDt = info.IssueApprovalDt;
+            if (string.IsNullOrEmpty(info.Client_VisaInformationDt)) info.Client_VisaInformationDt = info.VisaInformationDt;
+            if (string.IsNullOrEmpty(info.Client_SendVisaDt)) info.Client_SendVisaDt = info.SendVisaDt;
+            if (string.IsNullOrEmpty(info.Client_IssueVisaDt)) info.Client_IssueVisaDt = info.IssueVisaDt;
+            if (string.IsNullOrEmpty(info.Client_AirTicketDt)) info.Client_AirTicketDt = info.AirTicketDt;
+            if (string.IsNullOrEmpty(info.Client_HotelDt)) info.Client_HotelDt = info.HotelDt;
+            if (string.IsNullOrEmpty(info.Client_PreTripMeetingDt)) info.Client_PreTripMeetingDt = info.PreTripMeetingDt;
+            if (string.IsNullOrEmpty(info.Client_AirportdDropOffDt)) info.Client_AirportdDropOffDt = info.AirportdDropOffDt;
+
+            #endregion
+
             string visaSql = string.Format(@$"Select * From Grp_InvertedListVisaCountry Where Isdel={0} And ILId = {ilId}");
             var visaCountryInfo = await _sqlSugar.SqlQueryable<VisaCountryInfo>(visaSql).ToListAsync();
 
@@ -167,7 +181,7 @@ namespace OASystem.Infrastructure.Repositories.Groups
         /// </summary>
         /// <param name="diId"></param>
         /// <returns></returns>
-        public async Task<Result> _Create(int userId,int diId,string remark = "")
+        public async Task<Result> Create(int userId,int diId,string remark = "")
         {
             #region 参数验证
             if (diId < 1)
@@ -258,22 +272,32 @@ namespace OASystem.Infrastructure.Repositories.Groups
                 sendVisa_advanceDays = -12,         //送签
                 issueVisa_advanceDays = -5,         //出签
                 preTripMeeting_advanceDays = -3,    //行前会
-                airportdDropOff_advanceDays = 0;   //送机
+                airportdDropOff_advanceDays = 0;    //送机
 
             var info = new Grp_InvertedList() { 
                 DiId = diId,
                 ApprovalDataDt = visitDt.AddDays(approvalData_advanceDays).ToString("yyyy-MM-dd"),
+                Client_ApprovalDataDt = visitDt.AddDays(approvalData_advanceDays).ToString("yyyy-MM-dd"),
                 ApprovalDt = visitDt.AddDays(approval_advanceDays).ToString("yyyy-MM-dd"),
+                Client_ApprovalDt = visitDt.AddDays(approval_advanceDays).ToString("yyyy-MM-dd"),
                 ApprovalType = -1,
                 IssueApprovalDt = visitDt.AddDays(IssueApproval_advanceDays).ToString("yyyy-MM-dd"),
+                Client_IssueApprovalDt = visitDt.AddDays(IssueApproval_advanceDays).ToString("yyyy-MM-dd"),
                 //ApplyPassportDt = visitDt.AddDays(ApplyPassport_advanceDays).ToString("yyyy-MM-dd"),
                 VisaInformationDt = visitDt.AddDays(VisaInformation_advanceDays).ToString("yyyy-MM-dd"),
+                Client_VisaInformationDt = visitDt.AddDays(VisaInformation_advanceDays).ToString("yyyy-MM-dd"),
                 SendVisaDt = visitDt.AddDays(sendVisa_advanceDays).ToString("yyyy-MM-dd"),
+                Client_SendVisaDt = visitDt.AddDays(sendVisa_advanceDays).ToString("yyyy-MM-dd"),
                 IssueVisaDt = visitDt.AddDays(issueVisa_advanceDays).ToString("yyyy-MM-dd"),
-                AirTicketDt = visitDt.AddDays(issueVisa_advanceDays).ToString("yyyy-MM-dd"), //机票 应国交部要求默认使用出签时间
-                HotelDt = visitDt.AddDays(issueVisa_advanceDays).ToString("yyyy-MM-dd"),     //酒店 应国交部要求默认使用出签时间
+                Client_IssueVisaDt = visitDt.AddDays(issueVisa_advanceDays).ToString("yyyy-MM-dd"),
+                AirTicketDt = visitDt.AddDays(issueVisa_advanceDays).ToString("yyyy-MM-dd"),        //机票 应国交部要求默认使用出签时间
+                Client_AirTicketDt = visitDt.AddDays(issueVisa_advanceDays).ToString("yyyy-MM-dd"), //机票 应国交部要求默认使用出签时间
+                HotelDt = visitDt.AddDays(issueVisa_advanceDays).ToString("yyyy-MM-dd"),            //酒店 应国交部要求默认使用出签时间
+                Client_HotelDt = visitDt.AddDays(issueVisa_advanceDays).ToString("yyyy-MM-dd"),     //酒店 应国交部要求默认使用出签时间
                 PreTripMeetingDt = visitDt.AddDays(preTripMeeting_advanceDays).ToString("yyyy-MM-dd"),
+                Client_PreTripMeetingDt = visitDt.AddDays(preTripMeeting_advanceDays).ToString("yyyy-MM-dd"),
                 AirportdDropOffDt = visitDt.AddDays(airportdDropOff_advanceDays).ToString("yyyy-MM-dd"),
+                Client_AirportdDropOffDt = visitDt.AddDays(airportdDropOff_advanceDays).ToString("yyyy-MM-dd"),
                 CreateUserId = userId,
                 Remark = remark
             };
@@ -290,12 +314,12 @@ namespace OASystem.Infrastructure.Repositories.Groups
                 return _result;
             }
 
-            var _InvertedListVisaCountries = new List<Grp_InvertedListVisaCountry>();
+            var invertedListVisaCountries = new List<Grp_InvertedListVisaCountry>();
             foreach (var item in visitCountry)
             {
                 int days = Convert.ToInt32(visaFeeDatas.Find(x => x.VisaCountry.Equals(item.Trim()))?.VisaTime ?? "0");
-                
-                _InvertedListVisaCountries.Add(new Grp_InvertedListVisaCountry()
+
+                invertedListVisaCountries.Add(new Grp_InvertedListVisaCountry()
                 {
                     ILId = add1,
                     Country = item,
@@ -305,7 +329,7 @@ namespace OASystem.Infrastructure.Repositories.Groups
                 });
             }
 
-            int add2 = await _sqlSugar.Insertable<Grp_InvertedListVisaCountry>(_InvertedListVisaCountries).ExecuteReturnIdentityAsync();
+            int add2 = await _sqlSugar.Insertable<Grp_InvertedListVisaCountry>(invertedListVisaCountries).ExecuteReturnIdentityAsync();
 
             _sqlSugar.CommitTran();
             _result.Code = 0;
@@ -318,7 +342,7 @@ namespace OASystem.Infrastructure.Repositories.Groups
         /// </summary>
         /// <param name="diId"></param>
         /// <returns></returns>
-        public async Task<Result> _Update(InvertedListUpdateDto dto)
+        public async Task<Result> Update(InvertedListUpdateDto dto)
         {
             #region 参数验证
             if (dto.DiId < 1)
@@ -372,6 +396,5 @@ namespace OASystem.Infrastructure.Repositories.Groups
             return _result;
         }
     
-    
     }
 }

+ 46 - 31
OASystem/OASystem.Infrastructure/Repositories/Groups/ProcessOverviewRepository.cs

@@ -71,6 +71,11 @@ namespace OASystem.Infrastructure.Repositories.Groups
                 })
                 .ToListAsync();
 
+            var defaultJobNames = new List<string>()
+            {
+                "OP主管"
+            };
+
             #region 商邀报批流程
 
             string oaNode1Tips = NodeTipsMsg(groupInfo, GroupProcessType.Invitation, 1);
@@ -157,8 +162,13 @@ namespace OASystem.Infrastructure.Repositories.Groups
             string airNode8Tips = NodeTipsMsg(groupInfo, GroupProcessType.AirTicket, 8);
 
             //节点可操作用户列表
+            var airNodeOpJobNames = new List<string>() {
+                "机票"
+            };
+            airNodeOpJobNames.AddRange(defaultJobNames);
+
             var airNodeOpUsers = users.Where(u =>
-                u.JobName != null && u.JobName.Contains("机票")
+                u.JobName != null && airNodeOpJobNames.Contains(u.JobName)
             ).Select(u => u.Id).ToList();
 
             processs.Add(
@@ -179,7 +189,6 @@ namespace OASystem.Infrastructure.Repositories.Groups
             #endregion
 
             #region 酒店流程
-
             string hotelNode1Tips = NodeTipsMsg(groupInfo, GroupProcessType.Hotel, 1);
             string hotelNode2Tips = NodeTipsMsg(groupInfo, GroupProcessType.Hotel, 2);
             string hotelNode3Tips = NodeTipsMsg(groupInfo, GroupProcessType.Hotel, 3);
@@ -187,8 +196,11 @@ namespace OASystem.Infrastructure.Repositories.Groups
             string hotelNode5Tips = NodeTipsMsg(groupInfo, GroupProcessType.Hotel, 5);
 
             //节点可操作用户列表
+            var hotelNodeOpJobNames = new List<string>() { "酒店" };
+            hotelNodeOpJobNames.AddRange(defaultJobNames);
+
             var hotelNodeOpUsers = users.Where(u =>
-                u.JobName != null && u.JobName.Contains("酒店")
+                u.JobName != null && hotelNodeOpJobNames.Contains(u.JobName)
             ).Select(u => u.Id).ToList();
 
             processs.Add(
@@ -215,8 +227,11 @@ namespace OASystem.Infrastructure.Repositories.Groups
             string opNode7Tips = NodeTipsMsg(groupInfo, GroupProcessType.LocalGuide, 7);
 
             //节点可操作用户列表
+            var opNodeOpJobNames = new List<string>() { "OP" };
+            opNodeOpJobNames.AddRange(defaultJobNames);
+
             var opNodeOpUsers = users.Where(u =>
-                u.JobName != null && u.JobName.Equals("OP")
+                u.JobName != null && opNodeOpJobNames.Contains( u.JobName)
             ).Select(u => u.Id).ToList();
 
             processs.Add(
@@ -667,23 +682,25 @@ namespace OASystem.Infrastructure.Repositories.Groups
                 {
                     // 1. 获取节点和流程信息
                     var node = await _sqlSugar.Queryable<Grp_ProcessNode>()
-                        .FirstAsync(n => n.Id == nodeId && n.IsDel == 0)
-                        ?? throw new BusinessException("当前节点不存在或已被删除。");
+                        .FirstAsync(n => n.Id == nodeId && n.IsDel == 0);
+
+                    if (node == null) return new Result { Code = StatusCodes.Status400BadRequest, Msg = "当前节点不存在或已被删除。" };
 
                     // 2. 用户权限验证
                     if (!HasNodeOperationPermission(node, currUserId))
                     {
-                        throw new BusinessException("当前用户没有操作此节点的权限。");
+                        return new Result { Code = StatusCodes.Status400BadRequest, Msg = "当前用户没有操作此节点的权限." };
                     }
 
                     var process = await _sqlSugar.Queryable<Grp_ProcessOverview>()
-                        .FirstAsync(p => p.Id == node.ProcessId && p.IsDel == 0)
-                        ?? throw new BusinessException("关联的流程不存在。");
+                        .FirstAsync(p => p.Id == node.ProcessId && p.IsDel == 0);
+
+                    if (process == null) return new Result { Code = StatusCodes.Status400BadRequest, Msg = "关联的流程不存在。" };
 
                     // 3. 检查是否重复操作
                     if (node.OverallStatus == targetStatus)
                     {
-                        throw new BusinessException($"当前节点已为{GetStatusDescription(targetStatus)}状态,无需重复操作。");
+                        return new Result { Code = StatusCodes.Status400BadRequest, Msg = $"当前节点已为{GetStatusDescription(targetStatus)}状态,无需重复操作。。" };
                     }
 
                     // 4. 存储更新前的值
@@ -1349,18 +1366,20 @@ namespace OASystem.Infrastructure.Repositories.Groups
 
             // 1. 获取并验证节点和流程
             var node = await _sqlSugar.Queryable<Grp_ProcessNode>()
-                .FirstAsync(n => n.Id == nodeId && n.IsDel == 0)
-                ?? throw new BusinessException("当前节点不存在或已被删除。");
+                .FirstAsync(n => n.Id == nodeId && n.IsDel == 0);
+
+            if (node == null) return new Result { Code = 400, Msg = "当前节点不存在或已被删除。" };
 
             // 1.1. 用户权限验证
             if (!HasNodeOperationPermission(node, currUserId))
             {
-                throw new BusinessException("当前用户没有操作此节点的权限。");
+                return new Result { Code = 400, Msg = "当前用户没有操作此节点的权限。" };
             }
 
             var process = await _sqlSugar.Queryable<Grp_ProcessOverview>()
-                .FirstAsync(p => p.Id == node.ProcessId && p.IsDel == 0)
-                ?? throw new BusinessException("当前流程不存在或已被删除。");
+                .FirstAsync(p => p.Id == node.ProcessId && p.IsDel == 0);
+
+            if (process == null) return new Result { Code = 400, Msg = "当前流程不存在或已被删除。" };
 
             // 2.1 存储更新前流程及节点信息
             var nodeBefore = CloneNode(node);
@@ -1374,10 +1393,7 @@ namespace OASystem.Infrastructure.Repositories.Groups
             node.IsAssist = isAssist;
             node.IsFileUp = isFileUp;
             node.IsPart = isPart;
-            if (!string.IsNullOrEmpty(dto.Remark))
-            {
-                node.Remark = dto.Remark;
-            }
+            node.Remark = dto.Remark;
 
             // 3. 保存节点更新
             await _sqlSugar.Updateable(node)
@@ -1412,7 +1428,7 @@ namespace OASystem.Infrastructure.Repositories.Groups
 
             }
 
-            return new Result { Code = 200, Msg = "实际操作时间设置成功。" };
+            return new Result { Code = 200, Msg = "设置成功。" };
         }
 
         #endregion
@@ -1721,7 +1737,7 @@ namespace OASystem.Infrastructure.Repositories.Groups
                     var firstNode = await _sqlSugar.Queryable<Grp_ConfProcessNode>().FirstAsync(x => x.IsDel == 0 && x.ProcessId == existingProcesses.FirstOrDefault().Id);
                     if (!HasConfNodeOperationPermission(firstNode, currUserId))
                     {
-                        throw new BusinessException("当前用户没有操作此节点的权限。");
+                        return new Result { Code = 400, Msg = "当前用户没有操作此节点的权限。" };
                     }
 
                     //团组会流程完成 不可切换模板
@@ -1789,23 +1805,25 @@ namespace OASystem.Infrastructure.Repositories.Groups
                 {
                     // 1. 获取节点和流程信息
                     var node = await _sqlSugar.Queryable<Grp_ConfProcessNode>()
-                        .FirstAsync(n => n.Id == nodeId && n.IsDel == 0)
-                        ?? throw new BusinessException("当前节点不存在或已被删除。");
+                        .FirstAsync(n => n.Id == nodeId && n.IsDel == 0);
+
+                    if (node == null) return new Result { Code = StatusCodes.Status400BadRequest, Msg = "当前节点不存在或已被删除。" };
 
                     // 2. 用户权限验证
                     if (!HasConfNodeOperationPermission(node, currUserId))
                     {
-                        throw new BusinessException("当前用户没有操作此节点的权限。");
+                        return new Result { Code = StatusCodes.Status400BadRequest, Msg = "当前用户没有操作此节点的权限。" };
                     }
 
                     var process = await _sqlSugar.Queryable<Grp_ConfProcessOverview>()
-                        .FirstAsync(p => p.Id == node.ProcessId && p.IsDel == 0)
-                        ?? throw new BusinessException("关联的流程不存在。");
+                        .FirstAsync(p => p.Id == node.ProcessId && p.IsDel == 0);
+
+                    if (process == null) return new Result { Code = StatusCodes.Status400BadRequest, Msg = "关联的流程不存在。" };
 
                     // 3. 检查是否重复操作
                     if (node.OverallStatus == targetStatus)
                     {
-                        throw new BusinessException($"当前节点已为{GetStatusDescription(targetStatus)}状态,无需重复操作。");
+                        return new Result { Code = StatusCodes.Status400BadRequest, Msg = "当前节点已为{GetStatusDescription(targetStatus)}状态,无需重复操作。。" };
                     }
 
                     // 4. 存储更新前的值
@@ -2238,10 +2256,7 @@ namespace OASystem.Infrastructure.Repositories.Groups
 
             node.IsFileUp = isFileUp;
             node.Participators = dto.Participators;
-            if (!string.IsNullOrEmpty(dto.Remark))
-            {
-                node.Remark = dto.Remark;
-            }
+            node.Remark = dto.Remark;
 
             // 3. 保存节点更新
             await _sqlSugar.Updateable(node)

+ 3 - 3
OASystem/OASystem.Infrastructure/Repositories/PersonnelModule/TaskAllocationRepository.cs

@@ -129,12 +129,12 @@ namespace OASystem.Infrastructure.Repositories.PersonnelModule
                 if (taskAudits.Any())
                 {
                     //任务权限
-                    if (taslPerm)
-                    {
+                    //if (taslPerm)
+                    //{
                         taskOpertionAudit.IsAddPerm = true;
                         taskOpertionAudit.IsDelPerm = true;
                         taskOpertionAudit.IsStopPerm = true;
-                    }
+                    //}
 
                     var userIds = taskAudits.Select(it => it.SubUserId).ToList();
                     string userSql = string.Format(@"Select u.Id,u.CnName As Name,c.CompanyName,