Bladeren bron

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

yuanrf 1 dag geleden
bovenliggende
commit
9bd36fc888

+ 2 - 1
OASystem/EntitySync/Program.cs

@@ -183,6 +183,7 @@ db.CodeFirst.SetStringDefaultLength(50).BackupTable().InitTables(new Type[]
     //typeof(Pm_CompanyDailyKpi),//财务部绩效考核    
     //typeof(Grp_ConfProcessOverview),//会务流程总览    
     //typeof(Grp_ConfProcessNode),//会务流程节点     
-    typeof(Grp_ConfProcessLog),//团组会务流程总览操作日志  
+    //typeof(Grp_ConfProcessLog),//团组会务流程总览操作日志  
+    typeof(Res_InvitationAI),//团组会务流程总览操作日志  
 });
 Console.WriteLine("数据库结构同步完成!");

File diff suppressed because it is too large
+ 1957 - 610
OASystem/OASystem.Api/Controllers/GroupsController.cs


+ 349 - 3
OASystem/OASystem.Api/Controllers/ResourceController.cs

@@ -1,17 +1,23 @@
 using Aspose.Cells;
 using Aspose.Words;
+using Dm.util;
+using EyeSoft.Collections.Generic;
 using EyeSoft.Extensions;
 using Microsoft.IdentityModel.Tokens;
+using NPOI.SS.UserModel;
 using OASystem.API.OAMethodLib;
+using OASystem.API.OAMethodLib.HunYuanAPI;
 using OASystem.API.OAMethodLib.QiYeWeChatAPI.AppNotice;
 using OASystem.Domain.AesEncryption;
 using OASystem.Domain.Dtos.Groups;
+using OASystem.Domain.Entities.Customer;
 using OASystem.Domain.Entities.Groups;
 using OASystem.Domain.ViewModels.Groups;
 using OASystem.Infrastructure.Repositories.Groups;
 using System.ComponentModel.DataAnnotations;
 using System.Data;
 using System.Diagnostics;
+using TencentCloud.Common;
 using static OASystem.API.OAMethodLib.JWTHelper;
 
 namespace OASystem.API.Controllers
@@ -24,8 +30,10 @@ namespace OASystem.API.Controllers
     public class ResourceController : ControllerBase
     {
         private readonly IMapper _mapper;
+        private readonly ILogger<ResourceController> _logger;
         private readonly SqlSugarClient _sqlSugar;
         private readonly IConfiguration _config;
+        private readonly IHunyuanService _hunyuanService;
         private readonly CarDataRepository _carDataRep;
         private readonly LocalGuideDataRepository _localGuideDataRep;
         private readonly ThreeCodeRepository _ThreeCodeRep;
@@ -62,6 +70,8 @@ namespace OASystem.API.Controllers
         public ResourceController(
             IMapper mapper,
             IConfiguration config,
+            ILogger<ResourceController> logger,
+            IHunyuanService hunyuanService,
             SqlSugarClient sqlSugar,
             CarDataRepository carDataRep,
             LocalGuideDataRepository localGuideDataRep,
@@ -88,6 +98,8 @@ namespace OASystem.API.Controllers
         {
             _mapper = mapper;
             _config = config;
+            _logger = logger;
+            _hunyuanService = hunyuanService;
             _sqlSugar = sqlSugar;
             _carDataRep = carDataRep;
             _localGuideDataRep = localGuideDataRep;
@@ -1525,8 +1537,6 @@ Inner Join Sys_Department as d With(Nolock) On u.DepId=d.Id Where m.Id={0} ", _m
                 _ioaDatas = _ioaDatas.Where(x => string.IsNullOrWhiteSpace(x.Contact) || !x.Contact.Contains(item)).ToList();
             }
 
-
-
             List<Sys_Users> _Users = _sqlSugar.Queryable<Sys_Users>().Where(it => it.IsDel == 0).ToList();
 
             var _countryData = _ioaDatas.Select(it => it.Country).Distinct().ToList(); _countryData.Remove("");
@@ -1719,7 +1729,6 @@ Inner Join Sys_Department as d With(Nolock) On u.DepId=d.Id Where m.Id={0} ", _m
             }
         }
 
-
         /// <summary>
         /// 商邀资料查询-欧洲
         /// </summary>
@@ -2262,6 +2271,343 @@ Inner Join Sys_Department as d With(Nolock) On u.DepId=d.Id Where m.Id={0} ", _m
 
         #endregion
 
+        #region 商邀资料 AI
+
+        /// <summary>
+        /// 商邀资料AI 基础数据源
+        /// </summary>
+        /// <returns></returns>
+        [HttpGet]
+        [ProducesResponseType(typeof(JsonView), StatusCodes.Status200OK)]
+        public async Task<IActionResult> InvitationAIInit()
+        {
+            // 预定义 UnionAll 查询
+            var query1 = _sqlSugar.Queryable<Grp_DelegationInfo>()
+                .Where(x => x.IsDel == 0 && !string.IsNullOrEmpty(x.TeamName))
+                .Select(x => new InvitationAIInvNameView { Id = x.Id, Name = x.TeamName, Source = 1, SortTime = x.VisitDate });
+
+            var query2 = _sqlSugar.Queryable<Res_InvitationAI>()
+                .Where(x => x.IsDel == 0 && !string.IsNullOrEmpty(x.InvName))
+                .Select(x => new InvitationAIInvNameView { Id = x.Id, Name = x.InvName, Source = 2, SortTime = x.CreateTime });
+
+            var itemNames = await _sqlSugar.UnionAll(query1, query2)
+                .OrderByDescending(x => x.SortTime)
+                .Select(x => new { x.Id, x.Name, x.Source }) 
+                .ToListAsync();
+
+            var invDatas = await _sqlSugar.Queryable<Crm_NewClientData>()
+                .Where(x => x.IsDel == 0)
+                .Select(x => x.Client)
+                .ToListAsync();
+
+            var countries = await _sqlSugar.Queryable<Sys_Countries>()
+                .Where(x => x.IsDel == 0)
+                .Select(x => x.Name_CN)
+                .Distinct()
+                .ToListAsync();
+
+            // 解密与去重(使用 HashSet 提升性能)
+            var unitNames = invDatas
+                .Select(item => AesEncryptionHelper.Decrypt(item))
+                .Where(val => !string.IsNullOrEmpty(val))
+                .Distinct()
+                .ToList();
+
+            return Ok(new
+            {
+                itemNames,
+                unitNames,
+                countries
+            });
+        }
+
+
+        /// <summary>
+        /// 商邀资料AI 混元AI查询资料
+        /// </summary>
+        /// <returns></returns>
+        [HttpGet("{name}")]
+        [ProducesResponseType(typeof(JsonView), StatusCodes.Status200OK)]
+        public async Task<IActionResult> InvitationAIItemByName(string name)
+        {
+            // 基础校验
+            if (string.IsNullOrWhiteSpace(name) )
+                return Ok(JsonView(false, "请传入有效的名称!"));
+
+            var infos = await _sqlSugar.Queryable<Res_InvitationAI>()
+                .Where(x => x.IsDel == 0 && x.InvName == name)
+                .Select(x => new { 
+                    x.Id,
+                    x.InvName,
+                    x.GroupId,
+                    x.AiCrawledDetails,
+                    Entry = x.Entries.FirstOrDefault(),
+                })
+                .FirstAsync();
+
+            return Ok(JsonView(true, $"查询成功!", infos));
+        }
+
+        /// <summary>
+        /// 商邀资料AI 混元AI查询资料
+        /// </summary>
+        /// <returns></returns>
+        [HttpPost]
+        [ProducesResponseType(typeof(JsonView), StatusCodes.Status200OK)]
+        public async Task<IActionResult> InvitationAISearch(InvitationAISearchDto dto)
+        {
+            // 基础校验
+            if (string.IsNullOrWhiteSpace(dto.UnitName) || string.IsNullOrWhiteSpace(dto.Country))
+                return Ok(JsonView(false, "请传入有效的单位名称和国家!"));
+
+            // 当前企业领域
+            string industryFocus = string.Empty;
+
+            // 动态计算 AI 需求缺口
+            int totalTarget = 15;
+
+            // 词条
+            string question = string.Empty;
+
+            var groupInfo = await _sqlSugar.Queryable<Grp_DelegationInfo>()
+                .Where(x => x.IsDel == 0 && x.Id == dto.GroupId)
+                .Select(x => new { x.TeamName, x.VisitPurpose })
+                .FirstAsync();
+
+            // 当前企业出访目的
+            string objective = groupInfo?.VisitPurpose ?? "商务考察与合作对接";
+
+            string operatorName = await _sqlSugar.Queryable<Sys_Users>().Where(x => x.IsDel == 0 && x.Id == dto.CurrUserId).Select(x => x.CnName).FirstAsync() ?? "-";
+
+            var localInvDatas = new List<InvitationAIInfo>(); // 本地数据源(商邀资料)
+
+            #region 本地数据源(商邀资料)
+
+            var rawData = await _sqlSugar.Queryable<Res_InvitationOfficialActivityData>()
+                .Where(x => x.IsDel == 0 && x.Country.Equals(dto.Country))
+                .ToListAsync();
+
+            // 解密
+            localInvDatas = rawData.AsParallel().AsOrdered().Select(item => new InvitationAIInfo
+            {
+                Source = 0, // 明确来源标识
+                Region = dto.UnitName,
+                NameCn = AesEncryptionHelper.Decrypt(item.UnitName),
+                Address = AesEncryptionHelper.Decrypt(item.Address),
+                Scope = AesEncryptionHelper.Decrypt(item.Field),
+                Contact = AesEncryptionHelper.Decrypt(item.Contact),
+                Phone = AesEncryptionHelper.Decrypt(item.Tel),
+                Email = AesEncryptionHelper.Decrypt(item.Email),
+                OperatedAt = DateTime.Now,
+                Operator = operatorName,
+            }).ToList();
+
+            #endregion
+
+            #region 混元AI 获取商邀资料
+
+            var hunyuanAIInvDatas = new List<InvitationAIInfo>();
+
+            int aiNeedCount = Math.Max(0, totalTarget - localInvDatas.Count);
+
+            if (aiNeedCount > 0)
+            {
+                question = @$"# [SYSTEM_CONTEXT]
+- Role: Senior Business Consultant (Global Supply Chain & Cross-border Trade Expert)
+- Framework: S.P.A.R. (Situation-Problem-Action-Result)
+- Target Architecture: .NET 6 DTO Compatible Interface
+
+# [INPUT_CONFIG]
+- OriginUnit: {{{dto.UnitName}}} 
+- TargetCountry: {{{dto.Country}}}
+- Objective: {{{objective}}}
+- DataCount: {{{aiNeedCount}}}
+- OtherConstraints: {{{dto.Remark}}}
+
+# [ROLE_DEFINITION]
+你是一位精通全球跨境经贸、海外园区政策及 {{TargetCountry}} 本地准入法规的【顶级商务咨询顾问】。你擅长通过“产业链对等原则(Chain-Parity Principle)”为跨国企业精准匹配具备落地价值的合作伙伴。
+
+# [BUSINESS_LOGIC_CoT]
+在生成结果前,请严格执行以下思维链拆解:
+1. **EntityProfiling**: 识别 {{OriginUnit}} 的核心生态位(如:Supply/Demand/Capital/Logistics)。
+2. **ParityMatching**: 检索 {{TargetCountry}} 境内业务闭环对等机构(例如:若 Origin 为分销,则 Target 为源头工厂/种植园)。
+3. **RegulatoryCheck**: 验证目标机构的合规性(如:GACC 备案、SPS 协议、或当地政府特许经营权)。
+4. **DataSynthesis**: 针对无法直接获取的动态(如 PostUrl),优先检索其官网 News 频道或 LinkedIn 企业号。
+
+# [CONSTRAINTS_&_STANDARDS]
+- **NamingConvention**: 所有 JSON Key 必须严格遵循 **PascalCase**(例如:`UnitNameCn` 而非 `unit_name_cn`)。
+- **DataIntegrity**: 
+    - 必须输出精确的 {{DataCount}} 条记录。
+    - 优先级:Core (核心机构) > Backup (关联替代机构)。
+- **ValidationRules**:
+    - `Phone`: 必须包含 {{TargetCountry}} 国际区号(如 +856, +66 等)。
+    - `IntgAdvice`: 必须包含“对等性分析”,解释该机构如何与 {{OriginUnit}} 形成业务闭环(50-100字)。
+    - `Status`: 若字段确实无法获取,统一填充 'N/A',禁止编造。
+- **Safety**: 确保推荐机构不涉及敏感黑名单或已破产企业。
+
+# [INFORMATION_SCHEMA]
+请将结果填充至以下结构的 JSON 数组中:
+- NameCn: 单位名称(中文)
+- NameEn: 单位名称(英文)
+- Address: 详细地理位置(含省市区街道)
+- Scope: 经营范围(需强调其出口配额、生产能力或行业地位)
+- Contact: 联系人姓名及职务
+- Phone: 拨打全号(含区号)
+- Email: 商务联络邮箱
+- SiteUrl: 官方网站或权威社媒主页
+- PostUrl: 近一年内的商务动态/新闻链接
+- RecLevel: 推荐等级(枚举值:Core, Backup)
+- IntgAdvice: 对接深度建议(基于产业链交合、互补逻辑)
+
+# [OUTPUT_PROTOCOL]
+- 仅输出一个标准的 JSON Array 字符串。
+- 严禁任何 Markdown 说明文字、代码块之外的解释或开场白。
+- 确保 JSON 语法在 .NET `JsonSerializer.Deserialize` 下可直接解析。
+
+# [EXECUTION]
+根据以上配置,开始生成。";
+
+                string response = string.Empty;
+                try
+                {
+                    response = await _hunyuanService.ChatCompletionsHunyuan_t1_latestAsync(question);
+                }
+                catch (HttpRequestException ex)
+                {
+                    _logger.LogError(ex, "网络连接失败,无法调用混元API");
+                    return Ok(JsonView(false, $"网络连接异常,请检查网络后重试!Ex:{ex.Message}"));
+                }
+                catch (TaskCanceledException ex)
+                {
+                    _logger.LogError(ex, "请求超时");
+                    return Ok(JsonView(false, $"AI 响应超时,请稍后再试!Ex:{ex.Message}"));
+                }
+                catch (TencentCloudSDKException ex)
+                {
+                    // 记录完整日志
+                    _logger.LogError(ex, "腾讯云API调用失败 | 错误码: {ErrorCode} | 请求ID: {RequestId}", ex.ErrorCode, ex.RequestId);
+
+                    // 根据错误码做差异化处理
+                    if (ex.ErrorCode != null && ex.ErrorCode == "AuthFailure.SignatureExpire")
+                    {
+                        return Ok(JsonView(false, $"系统时间异常,请同步时间后重试!Ex:{ex.Message}"));
+                    }
+                    else if (ex.ErrorCode != null && ex.ErrorCode.StartsWith("Unauthorized"))
+                    {
+                        return Ok(JsonView(false, $"当前账号无权限访问该服务!Ex:{ex.Message}"));
+                    }
+                    else
+                    {
+                        return Ok(JsonView(false, $"腾讯云服务调用失败,请稍后重试!Ex:{ex.Message}"));
+                    }
+                }
+                catch (Exception ex)
+                {
+                    _logger.LogError(ex, "未知错误,调用混元API失败");
+                    return Ok(JsonView(false, $"未知错误,调用混元API失败!Ex:{ex.Message}"));
+                }
+
+                if (!string.IsNullOrWhiteSpace(response))
+                {
+                    // 预处理:过滤 AI 可能返回的 Markdown 标记
+                    string cleanJson = response.Trim();
+                    if (cleanJson.StartsWith("```json"))
+                        cleanJson = cleanJson.Substring(7, cleanJson.Length - 10).Trim();
+                    else if (cleanJson.StartsWith("```"))
+                        cleanJson = cleanJson.Substring(3, cleanJson.Length - 6).Trim();
+
+                    try
+                    {
+                        // 解析并注入 Source 标识
+                        hunyuanAIInvDatas = JsonConvert.DeserializeObject<List<InvitationAIInfo>>(cleanJson);
+
+                        if (hunyuanAIInvDatas != null)
+                        {
+                            hunyuanAIInvDatas = hunyuanAIInvDatas.Select(x => {
+                                x.Source = 1;
+                                x.Region = dto.Country;
+                                x.Operator = operatorName;
+                                x.OperatedAt = DateTime.Now;
+                                return x;
+                            }).ToList();
+                        }
+                    }
+                    catch (JsonException ex)
+                    {
+                        // 记录日志并考虑 fallback 策略
+                        _logger.LogError(ex, "Hunyuan AI 响应解析失败。原始数据:{Response}", response);
+                    }
+                }
+            }
+
+            #endregion
+
+            #region 数据库操作
+
+            // 数据整合 (高效合并)
+            var finalResult = localInvDatas.Concat(hunyuanAIInvDatas).ToList();
+
+            // 词条信息
+            var entries = new List<EntryInfo>() { new EntryInfo() {
+                Details = question,
+                Operator = operatorName,
+                OperatedAt = DateTime.Now
+            }  };
+
+            string invName = $"{dto.UnitName}拜访{dto.Country}";
+
+            // 数据库信息获取方式
+            // 1.通过团组 GroupId 关联查询 
+            var dataInfo = await _sqlSugar.Queryable<Res_InvitationAI>().Where(x => x.IsDel == 0 && x.GroupId == dto.GroupId).FirstAsync();
+
+            // 2.通过InvName 关联查询(考虑到可能存在同名情况,优先使用 GroupId 关联查询,确保数据准确性)
+            dataInfo ??= await _sqlSugar.Queryable<Res_InvitationAI>().Where(x => x.IsDel == 0 && x.InvName == invName).FirstAsync();
+
+            // 3.如果以上两种方式都没有查询到数据,则说明是新数据,需要添加到数据库
+            if (dataInfo == null)
+            {
+                // 3.1 新数据,需要添加到数据库
+                dataInfo = new Res_InvitationAI()
+                {
+                    InvName = groupInfo?.TeamName ?? invName,  //默认团组名称
+                    GroupId = dto.GroupId,
+                    AiCrawledDetails = finalResult,
+                    Entries = entries,
+                    CreateUserId = dto.CurrUserId
+                };
+
+                var insert = await _sqlSugar.Insertable(dataInfo).ExecuteCommandAsync();
+                if (insert < 1)
+                {
+                    return Ok(JsonView(false, $"数据新增失败!"));
+                }
+            }
+            else
+            {
+                // 3.1 数据存在 则更新数据(覆盖原有的AI爬取详情,保留原有的其他字段不变)
+                dataInfo.AiCrawledDetails = finalResult;
+
+                var update = await _sqlSugar.Updateable(dataInfo).ExecuteCommandAsync();
+                if (update < 1)
+                {
+                    return Ok(JsonView(false, $"数据更新失败!"));
+                }
+            }
+
+            #endregion
+
+            return Ok(JsonView(true, $"查询成功!", new
+            {
+                dataInfo.Id,
+                dataInfo.InvName,
+                dataInfo.GroupId,
+                dataInfo.AiCrawledDetails,
+                Entry = dataInfo.Entries.FirstOrDefault(),
+            }));
+        }
+
+        #endregion
+
         #region 公务出访
         /// <summary>
         ///  获取团组所有信息,绑定下拉框

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

@@ -5886,7 +5886,6 @@ Where dfp.IsDel = 0
 -- And dfp.IsPay = 1
 ");//--Order By dfp.CreateTime Desc
 
-
                 if (_dto.Type == 1) //data
                 {
                     RefAsync<int> total = 0;

+ 5 - 1
OASystem/OASystem.Api/OAMethodLib/HunYuanAPI/HunyuanService.cs

@@ -16,7 +16,11 @@ namespace OASystem.API.OAMethodLib.HunYuanAPI
             _hunyuanClient = hunyuanClient;
         }
 
+        /// <summary>
         /// <inheritdoc />
+        /// </summary>
+        /// <param name="question"></param>
+        /// <returns></returns>
         public async Task<string> ChatCompletionsHunyuan_t1_latestAsync(string question)
         {
             var request = new ChatCompletionsRequest
@@ -36,7 +40,7 @@ namespace OASystem.API.OAMethodLib.HunYuanAPI
                 // 其他参数根据需要设置
             };
 
-            // 直接调用SDK方法
+            // 调用SDK方法
             var response = await _hunyuanClient.ChatCompletions(request);
 
             // 提取并返回模型生成的回答

+ 1 - 0
OASystem/OASystem.Api/OASystem.API.csproj

@@ -30,6 +30,7 @@
   </ItemGroup>
 
   <ItemGroup>
+    <None Remove="Controllers\5x5tfaby.3rg~" />
     <None Remove="Controllers\GroupsController.cs~RF185e674.TMP" />
     <None Remove="Controllers\GroupsController.cs~RF265115.TMP" />
   </ItemGroup>

+ 2 - 1
OASystem/OASystem.Api/Program.cs

@@ -530,7 +530,8 @@ builder.Services.AddSingleton(provider =>
     ClientProfile clientProfile = new ClientProfile();
     HttpProfile httpProfile = new HttpProfile
     {
-        Endpoint = "hunyuan.tencentcloudapi.com"
+        Endpoint = "hunyuan.tencentcloudapi.com",
+        Timeout = 60 * 10,  // µ¥Î»Ãë
     };
     clientProfile.HttpProfile = httpProfile;
 

+ 30 - 0
OASystem/OASystem.Domain/Dtos/Resource/InvitationAI.cs

@@ -0,0 +1,30 @@
+namespace OASystem.Domain.Dtos.Resource
+{
+    public class InvitationAI
+    {
+    }
+
+    /// <summary>
+    /// 商邀资料AI 混元AI查询资料 Dto
+    /// </summary>
+    public class InvitationAISearchDto
+    {
+        public int GroupId { get; set; }
+
+        /// <summary>
+        /// 出访单位
+        /// </summary>
+        public string UnitName { get; set; }
+        /// <summary>
+        /// 出访国家
+        /// </summary>
+        public string Country { get; set; }
+        /// <summary>
+        /// 备注信息
+        /// </summary>
+        public string Remark { get; set; }
+
+        public int CurrUserId { get; set; }
+    }
+
+}

+ 22 - 4
OASystem/OASystem.Domain/Entities/Resource/Res_InvitationAI.cs

@@ -46,7 +46,7 @@ namespace OASystem.Domain.Entities.Resource
     {
         /// <summary>
         /// 数据来源
-        /// 0-本地数据;1-网络爬取数据;2-第三方接口数据
+        /// 0-本地数据;1-第三方AI接口数据
         /// </summary>
         public int Source { get; set; } = 0;
 
@@ -56,9 +56,13 @@ namespace OASystem.Domain.Entities.Resource
         public string Region { get; set; }
 
         /// <summary>
-        /// 名称
+        /// 名称(中文)
+        /// </summary>
+        public string NameCn { get; set; }
+        /// <summary>
+        /// 名称(英文)
         /// </summary>
-        public string Name { get; set; }
+        public string NameEn { get; set; }
         /// <summary>
         /// 地址
         /// </summary>
@@ -76,14 +80,28 @@ namespace OASystem.Domain.Entities.Resource
         /// </summary>
         public string Phone { get; set; }
         /// <summary>
+        /// 联系邮箱
+        /// </summary>
+        public string Email { get; set; }
+        /// <summary>
         /// 官网地址
         /// </summary>
         public string SiteUrl { get; set; }
         /// <summary>
-        /// 当前文章地址
+        /// 文章地址
         /// </summary>
         public string PostUrl { get; set; }
 
+        /// <summary>
+        /// 推荐等级
+        /// </summary>
+        public string RecLevel { get; set; }
+
+        /// <summary>
+        /// 对接建议
+        /// </summary>
+        public string IntgAdvice { get; set; }
+
         /// <summary>
         /// 备注
         /// </summary>

+ 1 - 0
OASystem/OASystem.Domain/ViewModels/Groups/DelegationInfoView.cs

@@ -634,6 +634,7 @@ namespace OASystem.Domain.ViewModels.Groups
     /// </summary>
     public class CrmByGroupIdView
     {
+        public int DcId { get; set; }
         /// <summary>
         /// 团组Id
         /// </summary>

+ 24 - 0
OASystem/OASystem.Domain/ViewModels/Resource/InvitationOfficialActivityDataView.cs

@@ -220,4 +220,28 @@ namespace OASystem.Domain.ViewModels.Resource
         public string DelegationStr { get; set; }
 
     }
+
+    #region 商邀 AI 
+
+    public class InvitationAIInvNameView
+    {
+        /// <summary>
+        /// ID
+        /// </summary>
+        public int Id { get; set; } = 0;
+        /// <summary>
+        /// 名称
+        /// </summary>
+        public string Name { get; set; }
+
+        /// <summary>
+        /// 数据来源
+        /// 1:团组 2:商邀公务AI
+        /// </summary>
+        public int Source { get; set; }
+
+        public DateTime SortTime { get; set; }
+    }
+
+    #endregion
 }

+ 4 - 2
OASystem/OASystem.Infrastructure/Repositories/Groups/DelegationInfoRepository.cs

@@ -1308,7 +1308,7 @@ namespace OASystem.Infrastructure.Repositories.Groups
                         Id = x.Id,
                         FirstName = x.FirstName,
                         LastName = x.LastName,
-                        Tel = x.Tel
+                        Tel = x.Phone
                     })
                     .ToListAsync();
 
@@ -1332,12 +1332,14 @@ namespace OASystem.Infrastructure.Repositories.Groups
                 {
                     var idNo = AesEncryptionHelper.Decrypt(clientCertInfos.FirstOrDefault(x => x.DcId == item.Id)?.CertNo ?? "") ?? "-";
 
+                    var phone = AesEncryptionHelper.Decrypt(item.Tel);
                     if (string.IsNullOrEmpty(idNo)) idNo = "-";
 
                     view.Add(new() {
+                        DcId = item.Id,
                         GrpId = dto.GroupId,
                         ClientName = item.LastName + item.FirstName,
-                        Tel = item.Tel ?? "-",
+                        Tel = phone ?? "-",
                         CerdNo = idNo
                     });
                 }

+ 11 - 0
OASystem/OASystem.Infrastructure/Tools/CommonFun.cs

@@ -1035,4 +1035,15 @@ public static class CommonFun
     }
     #endregion
 
+    /// <summary>
+    /// Dictionary 取值工具
+    /// </summary>
+    /// <param name="dict"></param>
+    /// <param name="key"></param>
+    /// <returns></returns>
+    public static string GetSafeString(this Dictionary<string, string> dict, string key)
+    {
+        return dict.GetValueOrDefault(key) ?? string.Empty;
+    }
+
 }