Преглед изворни кода

AI商邀资料行业体系与配额调度重构升级

本次提交重构并升级了AI商邀资料相关核心逻辑,包括:
- 行业体系升级为多级IndustryTree,支持权重与扩展
- 新增AITaskItem与QuotaScheduler,实现多维度AI任务配额调度
- 提示词构建逻辑重构,增强业务约束与数据真实性校验
- 优化本地数据解密与筛选流程,提升并行效率
- 删除原InvitationAISearch接口,合并至流式接口,新增客户名单解密接口
- 更新混元API配置,优化代码结构,提升可维护性
Lyyyi пре 1 месец
родитељ
комит
62168d954e

+ 57 - 3
OASystem/OASystem.Api/Controllers/AITestController.cs

@@ -1,13 +1,15 @@
-using Microsoft.AspNetCore.Mvc;
-using OASystem.API.OAMethodLib.DeepSeekAPI;
 using Flurl.Http.Configuration;
+using Microsoft.AspNetCore.Mvc;
 using Microsoft.Extensions.Options;
+using OASystem.API.OAMethodLib.DeepSeekAPI;
 using OASystem.API.OAMethodLib.DoubaoAPI;
 using OASystem.API.OAMethodLib.Hotmail;
 using OASystem.API.OAMethodLib.HunYuanAPI;
 using OASystem.API.OAMethodLib.MicrosoftGraphMailbox;
 using OASystem.API.OAMethodLib.QiYeWeChatAPI;
 using OASystem.API.OAMethodLib.Quartz.Business;
+using OASystem.Domain.AesEncryption;
+using OASystem.Domain.Entities.Customer;
 using OASystem.Domain.ViewModels.QiYeWeChat;
 using OASystem.RedisRepository;
 using System.IdentityModel.Tokens.Jwt;
@@ -31,6 +33,7 @@ namespace OASystem.API.Controllers
         private readonly HotmailService _hotmailService;
         private readonly IMicrosoftGraphMailboxService _microsoftGraphMailboxService;
         private readonly IOptionsMonitor<MicrosoftGraphMailboxOptions> _microsoftGraphMailboxOptions;
+        private readonly MessageRepository _message;
 
         private readonly IDeepSeekService _deepSeekService;
 
@@ -44,7 +47,8 @@ namespace OASystem.API.Controllers
             IConfiguration config,
             IMicrosoftGraphMailboxService microsoftGraphMailboxService,
             IOptionsMonitor<MicrosoftGraphMailboxOptions> microsoftGraphMailboxOptions,
-            IDeepSeekService deepSeekService
+            IDeepSeekService deepSeekService,
+            MessageRepository message
             )
         {
             _hunyuanService = hunyuanService;
@@ -57,6 +61,7 @@ namespace OASystem.API.Controllers
             _microsoftGraphMailboxService = microsoftGraphMailboxService;
             _deepSeekService = deepSeekService;
             _microsoftGraphMailboxOptions = microsoftGraphMailboxOptions;
+            _message = message;
         }
 
         #region 企业微信发送邮件测试
@@ -657,5 +662,54 @@ namespace OASystem.API.Controllers
 
         #endregion
 
+
+        #region 客户名单解密
+
+        /// <summary>
+        /// 客户名单解密
+        /// </summary>
+        [HttpPost("deleClientList")]
+        public async Task<ActionResult<string>> DeleClientList()
+        {
+            var data = await _message._sqlSugar.Queryable<Crm_DeleClient>().Where(x => x.IsDel == 0 )
+                .LeftJoin<Crm_CustomerCompany>((x,y) => x.CrmCompanyId == y.Id)
+                .Select((x, y) => new { 
+                    x.Id,
+                    x.FirstName,
+                    x.LastName,
+                    y.CompanyFullName,
+                    x.ClientPhone,
+                    x.Tel,
+                    x.Phone,
+                    x.Job,
+                    x.CreateTime
+                }).ToListAsync();
+
+
+            var newData = new List<dynamic>();
+            foreach (var item in data)
+            {
+                newData.Add(new
+                {
+                    item.Id,
+                    LastName = AesEncryptionHelper.Decrypt(item.LastName),
+
+                    FirstName = AesEncryptionHelper.Decrypt(item.FirstName),
+                    CompanyFullName = AesEncryptionHelper.Decrypt(item.CompanyFullName),
+                    Job = AesEncryptionHelper.Decrypt(item.Job),
+                    ClientPhone = AesEncryptionHelper.Decrypt(item.ClientPhone),
+                    Tel = AesEncryptionHelper.Decrypt(item.Tel),
+                    Phone = AesEncryptionHelper.Decrypt(item.Phone),
+                    item.CreateTime
+
+                });
+            }
+
+
+            return StatusCode(200, newData);
+        }
+
+        #endregion
+
     }
 }

+ 462 - 327
OASystem/OASystem.Api/Controllers/ResourceController.cs

@@ -2267,10 +2267,10 @@ Inner Join Sys_Department as d With(Nolock) On u.DepId=d.Id Where m.Id={0} ", _m
         [ProducesResponseType(typeof(JsonView), StatusCodes.Status200OK)]
         public async Task<IActionResult> InvitationAIInit()
         {
-            var itemNames = await GeneralMethod.InvitationAIInvName();
-            var unitNames = await GeneralMethod.InvitationAIClientName();
-            var countries = await GeneralMethod.InvitationAICountryName();
-            var industryNodes = IndustryNode.BuildInitialData().Select(x => x.NameCn).ToList();
+            var itemNames = await InvitationAIInvName();
+            var unitNames = await InvitationAIClientName();
+            var countries = await InvitationAICountryName();
+            var industryNodes = IndustryTree.Build().Select(x => x.NameCn).ToList();
             var orgScales = OrgScale.BuildInitialData().Select(x => x.Name).ToList();
 
             return Ok(JsonView(true, $"查询成功!", new
@@ -2358,260 +2358,6 @@ Inner Join Sys_Department as d With(Nolock) On u.DepId=d.Id Where m.Id={0} ", _m
             }));
         }
 
-        /// <summary>
-        /// 商邀资料AI 混元AI查询资料
-        /// </summary>
-        /// <returns></returns>
-        [HttpPost]
-        [ProducesResponseType(typeof(JsonView), StatusCodes.Status200OK)]
-        public async Task<IActionResult> InvitationAISearch(InvitationAISearchDto dto)
-        {
-            var invAiInfo = await _sqlSugar.Queryable<Res_InvitationAI>().Where(x => x.Id == dto.Id).FirstAsync();
-
-            if (invAiInfo == null || invAiInfo?.EntryInfo == null)
-            {
-                return Ok(JsonView(false, "请先设置关键字信息!"));
-            }
-
-            var entryInfo = invAiInfo.EntryInfo;
-
-            // 当前企业领域
-            string industryFocus = string.Empty;
-
-            // 动态计算 AI 需求缺口
-            int totalTarget = entryInfo.NeedCount;
-
-            // 词条
-            string question = string.Empty;
-
-            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>(); // 本地数据源(商邀资料)
-            var aiTasks = new List<CountryAIPormptInfo>();    // 记录:国家 -> 需要补齐的数量
-
-            #region 本地数据源(商邀资料)
-
-            var datas = await _sqlSugar.Queryable<Res_InvitationOfficialActivityData>()
-                .Where(x => x.IsDel == 0)
-                .Select(x => new { 
-                    x.Id,
-                    x.Country
-                })
-                .ToListAsync();
-
-            var decryptDatas = new List<Res_InvitationOfficialActivityData>();
-            foreach (var item in datas)
-            {
-                decryptDatas.Add(new() { 
-                    Id = item.Id,
-                    Country = AesEncryptionHelper.Decrypt(item.Country)
-                });
-            }
-
-            var localDatas = decryptDatas.Where(x=> !string.IsNullOrEmpty(x.Country) && entryInfo.TargetCountry.Contains(x.Country)).ToList();
-
-            var localDataIds = localDatas.Select(x => x.Id).ToList();
-
-            var rawData = await _sqlSugar.Queryable<Res_InvitationOfficialActivityData>()
-                .Where(x => localDataIds.Contains(x.Id))
-                .ToListAsync();
-
-            // 解密 
-            var localInvDecryptDatas = rawData.AsParallel().AsOrdered().Select(item => new InvitationAIInfo
-            {
-                Guid = Guid.NewGuid().ToString("N"),
-                Source = 0, // 明确来源标识
-                Region = AesEncryptionHelper.Decrypt(item.Country),
-                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();
-
-            // 国家数据条数
-            int targetPerCountry = invAiInfo.EntryInfo?.NeedCount ?? 10;
-            foreach (var countryName in invAiInfo.EntryInfo.TargetCountry)
-            {
-                var countryDatas = localInvDecryptDatas.Where(x => x.Region == countryName).Take(targetPerCountry).ToList();
-                if (countryDatas.Any())
-                {
-                    localInvDatas.AddRange(countryDatas);
-                    int gap = targetPerCountry - countryDatas.Count;
-                    if (gap > 0) aiTasks.Add(new() { Country = countryName, Count = gap });
-                }
-            }
-
-            #endregion
-
-            #region 混元AI 获取商邀资料
-
-            var hunyuanAIInvDatas = new List<InvitationAIInfo>();
-
-            if (aiTasks != null && aiTasks.Count > 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]
-- Tasks: {{{JsonConvert.SerializeObject(aiTasks)}}}
-- OriginUnit: {{{entryInfo.OriginUnit}}} 
-- Objective: {{{entryInfo.Objective}}}
-- OtherConstraints: {{{entryInfo.OtherConstraints}}}
-# [ROLE_DEFINITION]
-你是一位精通全球跨境经贸、海外园区政策及 Tasks 中的国家本地准入法规的【顶级商务咨询顾问】。你擅长通过“产业链对等原则(Chain-Parity Principle)”为跨国企业精准匹配具备落地价值的合作伙伴。
-
-# [BUSINESS_LOGIC_CoT]
-在生成结果前,请严格执行以下思维链拆解:
-1. **ScopePartitioning**: 遍历 Tasks 中的每个国家。
-1. **EntityProfiling**: 识别 {{OriginUnit}} 的核心生态位(如:Supply/Demand/Capital/Logistics)。
-2. **ParityMatching**: 针对每个国家,检索境内业务闭环对等机构。(例如:若 Origin 为分销,则 Target 为源头工厂/种植园)。
-3. **RegulatoryCheck**: 验证目标机构的合规性(如:GACC 备案、SPS 协议、或当地政府特许经营权)。
-4. **DataSynthesis**: 必须严格根据每个国家对应的 Count 生成数据条数。针对无法直接获取的动态(如 PostUrl),优先检索其官网 News 频道或 LinkedIn 企业号。
-
-# [CONSTRAINTS_&_STANDARDS]
-- **NamingConvention**: 所有 JSON Key 必须严格遵循 **PascalCase**(例如:`UnitNameCn` 而非 `unit_name_cn`)。
-- **DataIntegrity**: 
-    - 总条数必须等于 Tasks 中所有 Count 的总和。
-    - 优先级:Core (核心机构) > Backup (关联替代机构)。
-- **ValidationRules**:
-    - `Phone`: 必须包含 Tasks 中的国家国际区号(如 +856, +66 等)。
-    - `IntgAdvice`: 必须包含“对等性分析”,解释该机构如何与 {{OriginUnit}} 形成业务闭环(50-100字)。
-    - `Status`: 若字段确实无法获取,统一填充 'N/A',禁止编造。
-- **Safety**: 确保推荐机构不涉及敏感黑名单或已破产企业。
-
-# [INFORMATION_SCHEMA]
-请将结果填充至以下结构的 JSON 数组中:
-- Region:国家(必须与 Tasks 中的 Country 完全匹配)
-- 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.Guid = Guid.NewGuid().ToString("N");
-                                x.Source = 1;
-                                //x.Region = entryInfo.TargetCountry;
-                                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();
-
-            string invName = $"{entryInfo.OriginUnit}拜访{entryInfo.TargetCountry}";
-
-            invAiInfo.AiCrawledDetails = finalResult;
-
-            var update = await _sqlSugar.Updateable(invAiInfo).ExecuteCommandAsync();
-            if (update < 1)
-            {
-                return Ok(JsonView(false, $"数据更新失败!"));
-            }
-
-            #endregion
-
-            return Ok(JsonView(true, $"查询成功!", new
-            {
-                invAiInfo.Id,
-                invAiInfo.InvName,
-                invAiInfo.GroupId,
-                AiCrawledDetails = invAiInfo.AiCrawledDetails.OrderByDescending(x => x.OperatedAt).ToList(),
-                Entry = invAiInfo.EntryInfo
-            }));
-        }
-
         /// <summary>
         /// 商邀资料AI 混元AI查询资料(SSE流式推送)
         /// </summary>
@@ -2645,7 +2391,7 @@ Inner Join Sys_Department as d With(Nolock) On u.DepId=d.Id Where m.Id={0} ", _m
                 #region 2. 内存计算优化
                 // 仅查询必要字段,减少 DataReader 压力
                 var rawLocalDatas = await _sqlSugar.Queryable<Res_InvitationOfficialActivityData>()
-                    .Where(x => x.IsDel == 0)
+                    .Where(x => x.IsDel == 0 && !string.IsNullOrEmpty(x.UnitName))
                     .Select(x => new { x.Country, x.UnitName, x.Address, x.Field, x.Contact, x.Tel, x.Email })
                     .ToListAsync();
 
@@ -2667,6 +2413,8 @@ Inner Join Sys_Department as d With(Nolock) On u.DepId=d.Id Where m.Id={0} ", _m
 
                 // 筛选符合国家的本地数据
                 var matchedCountries = allDecrypted.Where(x => targetCountrySet.Contains(x.Region)).ToList();
+                //var matchedCountries = new List<InvitationAIInfo>();
+
                 #endregion
 
                 #region 3. 混元 AI 协同炼金 (双阶段)
@@ -2681,7 +2429,7 @@ Inner Join Sys_Department as d With(Nolock) On u.DepId=d.Id Where m.Id={0} ", _m
                     var industryMatches = CleanAndParseJson<List<IndustryMatchResult>>(industryRaw) ?? new();
                     var matchedNames = new HashSet<string>(industryMatches.Select(x => x.TargetUnitName));
                     // 重新过滤:仅保留 AI 认为匹配的本地数据
-                    matchedCountries = matchedCountries.Where(x => matchedNames.Contains(x.NameCn)).Distinct().ToList();
+                    matchedCountries = matchedCountries.Where(x => !string.IsNullOrEmpty(x.NameCn) && matchedNames.Contains(x.NameCn)).Distinct().ToList();
                 }
 
                 // --- 阶段 B: 差额补全 (Gap Filling) ---
@@ -2703,9 +2451,17 @@ Inner Join Sys_Department as d With(Nolock) On u.DepId=d.Id Where m.Id={0} ", _m
                     // 强制冷却(应对 QPS 限制)
                     // 混元免费版或低阶版本通常有 1s/1次 的频率限制
                     await Task.Delay(1000);
+                    // 任务配置计算
+                    var countryTasks = QuotaScheduler.GenerateTasks(aiTasks, entryInfo.Industries, entryInfo.ScaleTypes);
 
-                    await HttpContext.SendSseStepAsync(60, $"AI 正在跨境检索缺失的 {aiTasks.Sum(x => x.Count)} 条单位资料...");
-                    string searchQuestion = BuildHunyuanPrompt(aiTasks, entryInfo);
+                    var countryTasksGroupBy = countryTasks.GroupBy(x => x.Region).Select(g => new
+                    {
+                        Region = g.Key,
+                        Counrt = g.Count()
+                    }).ToList();
+
+                    await HttpContext.SendSseStepAsync(60, $"AI 正在跨境检索缺失的 {string.Join(", ", countryTasksGroupBy.Select(x => $"{x.Region}({x.Counrt}条)"))} 单位资料...");
+                    string searchQuestion = BuildHunyuanPrompt(aiTasks, countryTasks, entryInfo);
                     string searchRaw = await _hunyuanService.ChatCompletionsHunyuan_t1_latestAsync(searchQuestion);
 
                     var aiParsed = CleanAndParseJson<List<InvitationAIInfo>>(searchRaw);
@@ -2713,7 +2469,7 @@ Inner Join Sys_Department as d With(Nolock) On u.DepId=d.Id Where m.Id={0} ", _m
                     {
                         hunyuanAIInvDatas = aiParsed.Select(x => {
                             x.Guid = Guid.NewGuid().ToString("N");
-                            x.Source = 1; // 标识来源:AI 炼金
+                            x.Source = 1; 
                             x.Operator = operatorName;
                             x.OperatedAt = DateTime.Now;
                             return x;
@@ -2789,7 +2545,7 @@ Inner Join Sys_Department as d With(Nolock) On u.DepId=d.Id Where m.Id={0} ", _m
                 .ToList();
 
             // 序列化数据
-            var industryStandard = IndustryNode.BuildInitialData().Select(x => x.NameCn).ToList();
+            var industryStandard = IndustryTree.Build().Select(x => x.NameCn).ToList();
             string industryStandardStr = string.Join("、", industryStandard);
             string countriesStr = string.Join(", ", entryInfo.TargetCountry);
             string jsonData = JsonConvert.SerializeObject(filteredData);
@@ -2847,88 +2603,465 @@ Inner Join Sys_Department as d With(Nolock) On u.DepId=d.Id Where m.Id={0} ", _m
             );
         }
 
+        #region 国家配额计算(根据 行业、规模)
+
+        public class TaskCoverageReport
+        {
+            public bool IsValid { get; set; }
+
+            public List<string> MissingRegions { get; set; } = new();
+            public List<string> MissingIndustries { get; set; } = new();
+            public List<string> MissingScales { get; set; } = new();
+
+            public string Summary =>
+                $"Valid={IsValid}, " +
+                $"MissingRegions={string.Join(",", MissingRegions)}, " +
+                $"MissingIndustries={string.Join(",", MissingIndustries)}, " +
+                $"MissingScales={string.Join(",", MissingScales)}";
+        }
+
+        public static class CountryToRegionMapper
+        {
+            /// <summary>
+            /// 直接返回中文国家名作为 Region
+            /// </summary>
+            public static string GetRegion(string country)
+            {
+                if (string.IsNullOrWhiteSpace(country))
+                    return "Other";
+
+                return country;
+            }
+        }
+
+        public record IndustryNode(
+            string Code,
+            string NameCn,
+            string NameEn,
+            double Weight = 1.0, // 1.0 代表主行业
+            List<IndustryNode>? Children = null
+        );
+
+        /// <summary>
+        ///  行业结构
+        /// </summary>
+        public static class IndustryTree
+        {
+            public static List<IndustryNode> Build() => new()
+            {
+                // 1. 工业与制造业
+                new("IND_MANU", "工业与制造业领域", "Industry & Manufacturing", 1.0,
+                    Children: new()
+                    {
+                        new("MANU_MACH", "机械制造", "Machinery Manufacturing", 0.9),
+                        new("MANU_AUTO", "汽车制造", "Automotive Manufacturing", 0.9,
+                            Children: new()
+                            {
+                                new("AUTO_NEV", "新能源汽车", "New Energy Vehicles", 0.9),
+                                new("AUTO_AD", "自动驾驶", "Autonomous Driving", 0.85),
+                                new("AUTO_PARTS", "汽车零部件", "Auto Parts", 0.7)
+                            }),
+                        new("MANU_SMART", "智能制造", "Smart Manufacturing", 0.85)
+                    }),
+
+                // 2. 能源与资源
+                new("ENERGY_RES", "能源与资源领域", "Energy & Resources", 1.0,
+                    Children: new()
+                    {
+                        new("ENERGY_NE", "新能源", "New Energy", 0.9),
+                        new("ENERGY_STORAGE", "储能技术", "Energy Storage", 0.85),
+                        new("ENERGY_GRID", "智慧电网", "Smart Grid", 0.8)
+                    }),
+
+                // 3. 交通运输与物流
+                new("TRANS_LOG", "交通运输与物流领域", "Transportation & Logistics", 1.0,
+                    Children: new()
+                    {
+                        new("LOG_SMART", "智慧物流", "Smart Logistics", 0.9),
+                        new("TRANS_PORT", "港口自动化", "Port Automation", 0.85),
+                        new("LOG_COLD", "冷链物流", "Cold Chain Logistics", 0.8)
+                    }),
+
+                // 4. 城乡建设与规划
+                new("URBAN_RURAL", "城乡建设与规划领域", "Urban & Rural Construction", 1.0,
+                    Children: new()
+                    {
+                        new("URBAN_SMART", "智慧城市", "Smart City", 0.9),
+                        new("URBAN_GREEN", "绿色建筑", "Green Building", 0.85),
+                        new("URBAN_UPDATE", "城市更新", "Urban Renewal", 0.8)
+                    }),
+
+                // 5. 生态环境与水务
+                new("ECO_ENV", "生态环境与水务领域", "Ecology & Water Affairs", 1.0,
+                    Children: new()
+                    {
+                        new("ENV_WATER", "水处理", "Water Treatment", 0.9),
+                        new("ENV_SOLID", "固废处理", "Solid Waste Treatment", 0.85),
+                        new("ENV_MONITOR", "环境监测", "Environmental Monitoring", 0.8)
+                    }),
+
+                // 6. 农业与食品
+                new("AGRI_FOOD", "农业与食品领域", "Agriculture & Food", 1.0,
+                    Children: new()
+                    {
+                        new("AGRI_SMART", "智慧农业", "Smart Agriculture", 0.9),
+                        new("FOOD_PROC", "农产品加工", "Food Processing", 0.85),
+                        new("AGRI_SEED", "种业技术", "Seed Technology", 0.8)
+                    }),
+
+                // 7. 金融与商贸
+                new("FIN_TRADE", "金融与商贸领域", "Finance & Commerce", 1.0,
+                    Children: new()
+                    {
+                        new("FIN_TECH", "金融科技", "FinTech", 0.9),
+                        new("TRADE_E", "跨境电商", "Cross-border E-commerce", 0.85),
+                        new("FIN_SUPPLY", "供应链金融", "Supply Chain Finance", 0.8)
+                    }),
+
+                // 8. 医药健康与康养
+                new("MED_HEALTH", "医药健康与康养领域", "Medicine & Health", 1.0,
+                    Children: new()
+                    {
+                        new("MED_BIO", "生物医药", "Biopharma", 0.9),
+                        new("MED_DEVICE", "医疗器械", "Medical Devices", 0.85),
+                        new("HEALTH_CARE", "康复养老", "Rehabilitation & Elderly Care", 0.8)
+                    }),
+
+                // 9. 文化旅游与体育
+                new("CULT_TOUR", "文化旅游与体育领域", "Culture, Tourism & Sports", 1.0,
+                    Children: new()
+                    {
+                        new("TOUR_DIGITAL", "数字文旅", "Digital Culture & Tourism", 0.9),
+                        new("SPORT_EVENT", "体育赛事运营", "Sports Event Management", 0.85),
+                        new("CULT_CREATIVE", "文创设计", "Cultural Creativity", 0.8)
+                    }),
+
+                // 10. 信息科技与数字经济
+                new("IT_DIGITAL", "信息科技与数字经济领域", "IT & Digital Economy", 1.0,
+                    Children: new()
+                    {
+                        new("IT_SOFT", "软件", "Software", 1.0,
+                            Children: new()
+                            {
+                                new("SOFT_SAAS", "SaaS", "SaaS", 0.9),
+                                new("IT_AI", "AI", "Artificial Intelligence", 0.9),
+                                new("IT_BIGDATA", "大数据", "Big Data", 0.85),
+                                new("IT_CLOUD", "云计算", "Cloud Computing", 0.6)
+                            }),
+                        new("IT_IOT", "工业互联网", "Industrial Internet", 0.85)
+                    }),
+
+                // 11. 教育与科技
+                new("EDU_TECH", "教育与科技领域", "Education & Technology", 1.0,
+                    Children: new()
+                    {
+                        new("EDU_ONLINE", "在线教育", "Online Education", 0.9),
+                        new("EDU_VOC", "职业教育", "Vocational Education", 0.85),
+                        new("EDU_INFO", "教育信息化", "Education Informatization", 0.8)
+                    }),
+
+                // 12. 社会服务与公共管理
+                new("SOC_SERVICE", "社会服务与公共管理领域", "Social Services", 1.0,
+                    Children: new()
+                    {
+                        new("GOV_SMART", "智慧政务", "Smart Government", 0.9),
+                        new("COMMUNITY", "社区治理", "Community Governance", 0.85),
+                        new("NGO", "公益慈善", "Charity & NGO", 0.7)
+                    }),
+
+                // 13. 其他重点领域
+                new("OTHER_KEY", "其他重点领域", "Other Key Fields", 1.0,
+                    Children: new()
+                    {
+                        new("EMERGENCY", "应急管理", "Emergency Management", 0.9),
+                        new("GEO_SURVEY", "地质勘察", "Geological Survey", 0.85),
+                        new("IP_SERVICE", "知识产权服务", "IP Services", 0.8)
+                    })
+            };
+        }
+
+        public static class IndustryExpander
+        {
+            public static List<string> Expand(
+                List<string> baseIndustries,
+                List<IndustryNode> tree)
+            {
+                var result = new HashSet<string>(StringComparer.OrdinalIgnoreCase);
+
+                foreach (var baseIndName in baseIndustries)
+                {
+                    var node = tree.FirstOrDefault(n =>
+                        n.NameCn.Equals(baseIndName, StringComparison.OrdinalIgnoreCase));
+
+                    if (node == null) continue;
+
+                    // 添加主行业
+                    result.Add(node.NameCn);
+
+                    // 递归添加子行业(按权重降序)
+                    if (node.Children != null)
+                    {
+                        AddChildrenRecursive(node.Children, result);
+                    }
+                }
+
+                return result.ToList();
+            }
+
+            private static void AddChildrenRecursive(
+                List<IndustryNode> nodes,
+                HashSet<string> result)
+            {
+                foreach (var child in nodes.OrderByDescending(n => n.Weight))
+                {
+                    result.Add(child.NameCn);
+                    if (child.Children != null)
+                    {
+                        AddChildrenRecursive(child.Children, result);
+                    }
+                }
+            }
+        }
+
+        public static class QuotaScheduler
+        {
+            /// <summary>
+            /// 国家配额计算(根据 行业、规模)
+            /// </summary>
+            /// <param name="countryTasks"></param>
+            /// <param name="industries"></param>
+            /// <param name="scales"></param>
+            /// <returns></returns>
+            public static List<AITaskItem> GenerateTasks(
+                List<CountryAIPormptInfo> countryTasks,
+                List<string> industries,
+                List<string> scales)
+            {
+                if (!countryTasks.Any() || !industries.Any() || !scales.Any())
+                    return new List<AITaskItem>();
+
+                var rnd = new Random();
+
+                // 1. 行业延伸
+                var expandedIndustries = IndustryExpander.Expand(
+                    industries,
+                    IndustryTree.Build()
+                );
+
+                // 2. Country -> Region (中文)
+                var regionGroups = countryTasks
+                    .Select(ct => new
+                    {
+                        Region = CountryToRegionMapper.GetRegion(ct.Country),
+                        ct.Count
+                    })
+                    .GroupBy(x => x.Region)
+                    .ToList();
+
+                int totalRequested = regionGroups.Sum(g => g.Sum(x => x.Count));
+
+                var tasks = new List<AITaskItem>();
+
+                int totalTaskCount = countryTasks.Sum(x => x.Count);
+
+                // 3. 按权重生成(Region 30%)
+                foreach (var group in regionGroups)
+                {
+                    double weight = (double)group.Sum(x => x.Count) / totalRequested;
+                    int quota = (int)Math.Round(weight * totalTaskCount * 0.3);
+
+                    for (int i = 0; i < quota; i++)
+                    {
+                        tasks.Add(new AITaskItem
+                        {
+                            Region = group.Key, // 中文国家名
+                            Industry = expandedIndustries[rnd.Next(expandedIndustries.Count)],
+                            Scale = scales[rnd.Next(scales.Count)]
+                        });
+                    }
+                }
+
+                return tasks
+                    .OrderBy(_ => rnd.Next())
+                    .ToList();
+            }
+        }
+
+        #endregion
+
         /// <summary>
         /// 混元提示词构建(高度定制化,适配商邀资料场景)
         /// </summary>
         /// <param name="tasks">包含国家及 Count 数量的任务列表</param>
         /// <param name="entryInfo">包含规则基础信息</param>
         /// <returns>最终构建的 System Prompt 字符串</returns>
-        private static string BuildHunyuanPrompt(List<CountryAIPormptInfo> tasks, EntryInfo entryInfo)
+        private static string BuildHunyuanPrompt(List<CountryAIPormptInfo> tasks, List<AITaskItem> countryTasks, EntryInfo entryInfo)
         {
             // 行业信息,用于提示词硬约束
-            string industryEnum = string.Join("、", IndustryNode.Roots.Select(x => x.NameCn));
+            string industryEnum = string.Join("、", IndustryTree.Build().Select(x => x.NameCn).ToList());
 
-            //构建其他约束条件字符串
-            var otherConstraintsStr = new StringBuilder();
-            if (entryInfo.Industries.Any()) otherConstraintsStr.Append($"- 行业信息: {string.Join("、", entryInfo.Industries)};");
-            if (entryInfo.ScaleTypes.Any()) otherConstraintsStr.Append($"- 单位规模: {string.Join("、", entryInfo.ScaleTypes)};");
-            if (entryInfo.IsBackground) otherConstraintsStr.Append($"- 单位是否包含华人背景: 是;");
-            if (!string.IsNullOrEmpty(entryInfo.OtherConstraints)) otherConstraintsStr.Append($"- 其他规则: {entryInfo.OtherConstraints};");
+            var businessConstraints = new StringBuilder();
+            if (entryInfo.Industries.Any()) businessConstraints.AppendLine($" - 行业信息: {string.Join("、", entryInfo.Industries)}");
+            if (entryInfo.ScaleTypes.Any()) businessConstraints.AppendLine($" - 单位规模: {string.Join("、", entryInfo.ScaleTypes)}");
+            if (entryInfo.IsBackground) businessConstraints.AppendLine($" - 单位是否包含华人背景: 是");
+            if (!string.IsNullOrEmpty(entryInfo.OtherConstraints)) businessConstraints.AppendLine($" - 其他规则: {entryInfo.OtherConstraints}");
+            if (businessConstraints == null || businessConstraints.Length == 0) businessConstraints.AppendLine("无");
 
-            return @$"
+            return $@"
 # [SYSTEM_ROLE]
-你是一位精通全球跨境经贸、海外园区政策及准入法规的【顶级商务咨询顾问】。同时,你具备资深的 .NET 6 软件架构思维,擅长生成高精度、符合强类型反序列化要求的结构化 JSON 数据。
+你是精通全球实时经贸情报与海外准入法规的【顶级商务咨询顾问】。
+你具备实时全网检索、多源交叉核验、AI幻觉零容忍能力,严格遵循“无检索不输出、无验证不回填、搜不到即熔断”原则。
+你具备资深.NET 6架构思维,输出JSON 100%符合强类型反序列化、零异常,可直接被 JsonConvert.DeserializeObject<List<T>> 解析。
 
 # [CONTEXT_ANALYSIS]
-- **发起单位 (OriginUnit)**: {entryInfo.OriginUnit}
-- **核心目标 (Objective)**: {entryInfo.Objective}
-- **行业归口枚举**: [{industryEnum}]
-- **业务约束条件**: {otherConstraintsStr}
-
-# [THOUGHT_PROCESS_LOGIC (CoT)]
-在构建每一条匹配数据前,请严格执行以下逻辑拆解,严禁盲目生成:
-1. **产业链定位分析 (Parity Logic)**: 深度分析 {entryInfo.OriginUnit} 在产业链中的位置。若其为制造方,则必须匹配具备当地分销能力的“贸易商”或“工程承包商”;若其为下游单位,则匹配上游“工厂”。严禁匹配直接竞争对手。
-2. **地域合规性校验**: 确保匹配的单位在指定任务国家(Tasks)真实存在,并具备当地市场准入资质。
-3. **时效性过滤**: 检索目标单位在 **2023-2026** 年间的动态。若无公开新闻,必须确保其官方网站(SiteUrl)具有真实度。
-4. **数据量校验**: 严格执行 Tasks 中的 `Count` 数量要求,总生成条数必须精准等于所有任务 Count 之和。
+• 当前核查时间 (CurrentDate): {DateTime.Now:yyyy-MM-dd}
+• 发起单位 (OriginUnit): {entryInfo.OriginUnit}
+• 核心目标 (Objective): {entryInfo.Objective}
+
+• 业务硬性约束 (BusinessConstraints):
+{businessConstraints}
+
+• 国家任务配置 (CountryTasks):
+{JsonConvert.SerializeObject(countryTasks)}
+
+• 任务配额 (Multi-Tasking):
+{JsonConvert.SerializeObject(tasks)}
+
+# [BUSINESS_CONSTRAINTS_SCHEMA - 业务硬性约束解析规则]
+BusinessConstraints 参数为结构化文本,解析规则如下:
+1. “行业信息”:允许检索的行业集合,多个用顿号分隔
+2. “单位规模”:允许检索的企业规模集合,多个用顿号分隔
+3. “单位是否包含华人背景”:是/否开关
+4. “其他规则”:自由文本补充说明
+5. 若内容为“无”,表示无额外业务约束
+
+⚠️ 重要绑定:
+• 所有 Task 的 Scale 必须来自“单位规模”
+
+# [INDUSTRY_ONTOLOGY_RULES - 行业本体与延伸规则]
+
+1. 行业结构定义:
+   • 每个行业包含:
+     - 主行业(NameCn)
+     - 子行业(Children)
+     - 权重(Weight,0.0–1.0)
+
+2. 延伸原则:
+   • 允许在主行业基础上延伸至其子行业
+   • 权重 ≥ 0.8 的子行业:优先使用
+   • 权重 < 0.8 的子行业:仅在配额不足时补充
+   • 严禁跨越大类(如:软件 ≠ 汽车制造)
+
+3. 示例(仅作参考):
+   • 软件
+     - SaaS (0.9)
+     - AI (0.9)
+     - 大数据 (0.85)
+     - 云计算 (0.6)
+
+4. 输出约束:
+   • Task 中的 Industry 字段
+   • 必须来源于同一主行业下的 NameCn
+
+# [REGION_MAPPING_RULE - 中文国家直连模式]
+• 映射规则:
+  - CountryTasks 中的 Country 字段(中文国家名)
+  - 将直接作为 Region 字段的值使用
+  - 不进行区域聚合(如:美国 ≠ North America)
+• 示例:
+  - Country = ""美国""  → Region = ""美国""
+  - Country = ""德国""  → Region = ""德国""
+• 兜底规则:
+  - 空值或无法识别 → Region = ""Other""
+
+# [REGION_QUOTA_PARSING_RULES]
+1. CountryTasks 结构:
+   {{
+     ""Country"": ""string"",   // 中文国家名
+     ""Count"": int
+   }}
+2. 映射规则:严格遵循 REGION_MAPPING_RULE
+3. [EXTREME_FALLBACK_RULES - 极端异常兜底]
+   • CountryTasks 为空数组或未提供 → 直接返回 []
+   • 配额调度出现除零/空引用风险 → 立即熔断,输出 []
+
+# [REALITY_CHECK_RULES - 分层验证标准]
+1. 强制全网检索({DateTime.Now.AddYears(-3).Year}-{DateTime.Now.Year}):对每个Region+NameEn执行多语言检索。若完全检索不到任何可交叉验证的信息,该企业条目将被剔除,不进入输出列表。
+2. 企业真实性“双轨制”核验:
+   • 轨道A(权威信源):目标国官方投资促进局、当地证券交易所、中国驻外使领馆经商处、邓白氏编码。
+   • 轨道B(主流可信商业信源):Crunchbase、LinkedIn Company Page、PitchBook、行业权威媒体、知名风投Portfolio、公司IR页面。
+3. 官网有效性“核心指标”校验(非404/5xx,36个月内有更新,否则 SiteUrl = ""INVALID_URL_REALITY_CHECK_FAILED"")。
+4. 新闻动态(PostUrl)“双要素”校验(近三年 + URL可访问)。
+5. 邮箱(Email)有效性校验(官方域名 + 收件能力验证,否则 Email = ""INVALID_EMAIL_REALITY_CHECK_FAILED"")。
+6. 搜不到即熔断:完全无轨道A/B信源 → 不输出该企业。
+
+# [DATA_SOURCE_INTEGRITY - 分层策略]
+• Core:通过轨道A且官网有效
+• Backup:未通过轨道A,但通过轨道B且官网基本有效
+• 无效:轨道A/B均未通过 → 不输出
+
+# [QUOTA_SCHEDULING - 配额调度算法(浮动上限版)]
+• 数据来源说明:
+  - Region   权重来自 CountryTasks(直接使用中文国家名)
+  - Industry 来自 BusinessConstraints(行业信息 + 延伸)
+  - Scale    来自 BusinessConstraints(单位规模)
+• 基础权重分配:Region 30% + Industry 40% + Scale 30%
+• 【浮动上限规则】:
+  - 严禁为了填满 Region 配额而编造数据。
+  - 如果某个国家(Region)在指定 Industry + Scale 下找不到足够的可验证企业,允许该 Region 的实际输出数量 < 理论配额。
+• 【名额再分配】:
+  - 空出的名额必须自动转移给同一 Industry / Scale 下数据质量更高的其他国家。
+
+# [THOUGHT_PROCESS_LOGIC]
+1. 解析 BusinessConstraints 获取 Industries / Scales
+2. 应用 Industry Extension Rules
+3. 解析 CountryTasks → Region 配额(理论值)
+4. 按 Region(中文国家) + Industry + Scale 实时检索
+5. 执行轨道A/B + 官网校验(遇空则跳过,不硬凑)
+6. PostUrl/Email 校验
+7. 触发浮动上限逻辑,进行名额再分配
+8. 输出纯净 JSON 数组
 
 # [STRICT_DATA_CONTRACT]
-1. **命名规范 (Mandatory)**: 所有 JSON Key 必须严格遵循 **PascalCase**(大驼峰命名法)。
-   - 正确示例: `NameCn`, `PostUrl`, `RecLevel`
-   - 错误示例: `name_cn`, `nameCn`
-2. **字段取值约束**:
-   - `Industry`: 必须且只能从枚举值 [{industryEnum}] 中选择其一,不得自行发明。
-   - `RecLevel`: 仅限使用 `Core` 或 `Backup`。
-3. **空值与集合处理**:
-   - 若某字符串字段缺失,填充 `""N/A""`。
-   - 若 `PostUrl` 数组无动态,必须返回 `[]`,严禁返回 `null`。
-4. **格式规范**: 
-   - `Phone`: 必须包含国际区号(如 +86, +856)。
-   - `Date`: 统一使用 `yyyy-MM-dd`。
-
-# [INFORMATION_SCHEMA]
-请将结果填充至以下结构的 JSON Array 中:
 {{
-  ""Region"": ""国家名称"",
-  ""Industry"": ""所属行业(必须是指定的枚举值)"",
-  ""NameCn"": ""单位名称(中文)"",
-  ""NameEn"": ""单位名称(英文)"",
-  ""Address"": ""详细地理位置/总部地址"",
-  ""Scope"": ""经营范围(侧重描述其在当地的行业地位或配套能力)"",
-  ""Contact"": ""联系人姓名及职务"",
-  ""Phone"": ""含区号的联系电话"",
-  ""Email"": ""商务联络邮箱"",
-  ""SiteUrl"": ""官方网站或权威主页链接"",
-  ""PostUrl"": [
-    {{
-      ""Date"": ""yyyy-MM-dd"",
-      ""Description"": ""近三年企业动态简述 (15-30字)"",
-      ""Url"": ""动态/新闻链接""
-    }}
-  ],
-  ""RecLevel"": ""推荐等级枚举值"",
-  ""IntgAdvice"": ""对接深度建议(50-100字,基于产业链对等逻辑分析匹配原因)""
+  ""Region"": ""string"",
+  ""Industry"": ""string"",
+  ""NameCn"": ""string"",
+  ""NameEn"": ""string"",
+  ""Address"": ""string"",
+  ""Scope"": ""string"",
+  ""Contact"": ""string"",
+  ""Phone"": ""string"",
+  ""Email"": ""string"",
+  ""SiteUrl"": ""string"",
+  ""PostUrl"": [ {{ ""Date"": ""yyyy-MM-dd"", ""Description"": ""string"", ""Url"": ""string"" }} ],
+  ""RecLevel"": ""Core|Backup"",
+  ""IntgAdvice"": ""string""
 }}
 
-# [OUTPUT_PROTOCOL - CRITICAL]
-- **MODE**: RAW_TEXT_STREAM
-- **FORBIDDEN**: 严禁包含任何 Markdown 格式标识符(如 ```json )。
-- **FORBIDDEN**: 严禁输出任何开场白、中间解释、结尾客套话或补充说明。
-- **REQUIREMENT**: 只允许输出一个以 `[` 开头,以 `]` 结尾的纯 JSON 字符串,确保其可直接被 `JsonConvert.DeserializeObject<List<T>>` 解析。
+# [OUTPUT_PROTOCOL]
+• MODE: RAW_TEXT_STREAM
+• FORMAT: 纯JSON数组、无Markdown、无注释、无开场白、无结尾
+• EMPTY_HANDLING: 无有效数据 → 直接返回 []
+• FORBIDDEN: 严禁编造、推测、幻觉、占位对象
+
+# [HUNYUAN_OUTPUT_GUARDRAILS]
+你是一个严格的 JSON 生成器,不是对话助手。
+禁止输出 Markdown、代码块标记、解释性文字、思考过程。
+首字符必须是 `[` 或 `{{`,末字符必须是 `]` 或 `}}`。
+若结果为空,仅输出 `[]`。
+请立即执行。
 
 # [EXECUTION]
-基于以上配置,立即处理以下任务列表:
-{JsonConvert.SerializeObject(tasks)}";
+立即执行:
+1. 按中文 CountryTasks 推导 Region 配额
+2. 应用行业延伸规则
+3. 按 Region(中文国家) + Industry + Scale 实时检索
+4. 执行轨道A/B + 官网校验(遇空则跳过)
+5. 对PostUrl/Email执行校验
+6. 执行名额再分配(浮动上限逻辑)
+7. 按配额输出真实企业
+8. 无真实数据 → 返回 []";
         }
 
         /// <summary>
@@ -3491,7 +3624,9 @@ Inner Join Sys_Department as d With(Nolock) On u.DepId=d.Id Where m.Id={0} ", _m
                 entryInfo.OtherConstraints = promptOther; // 将去重提示注入 entryInfo,确保 Prompt 构建时包含该信息
 
                 // 构建 Question 
-                string question = BuildHunyuanPrompt(aiTasks, entryInfo);
+                // 任务配置计算
+                var countryTasks = QuotaScheduler.GenerateTasks(aiTasks, entryInfo.Industries, entryInfo.ScaleTypes);
+                string question = BuildHunyuanPrompt(aiTasks, countryTasks, entryInfo);
 
                 await HttpContext.SendSseStepAsync(30, "AI 正在深度检索跨境商邀数据,请稍候...");
 

+ 12 - 4
OASystem/OASystem.Api/appsettings.json

@@ -588,11 +588,19 @@
     ]
   },
   "AllowedHosts": "*",
-  // 混元API 配置
+  //// 混元API 配置 - 杨俊霄
+  //"TencentCloud": {
+  //  "SecretId": "AKIDISQCm9K9wYDsT8hMuIVXO2WouugFpMlF",
+  //  "SecretKey": "PfleOvELH3dz9g4OWWKwLYXIp9F7mDUY",
+  //  "AppId": 100015480940,
+  //  "Region": "ap-chengdu",
+  //  "Version": "2023-09-01"
+  //},
+  // 混元API 配置 - 雷怡
   "TencentCloud": {
-    "SecretId": "AKIDISQCm9K9wYDsT8hMuIVXO2WouugFpMlF",
-    "SecretKey": "PfleOvELH3dz9g4OWWKwLYXIp9F7mDUY",
-    "AppId": 100015480940,
+    "SecretId": "AKIDpkTyUsENSTWZaPCqLuNmFetwytCLk4Tj",
+    "SecretKey": "EHJH4h8LJ6forpmpgN9u288KSQBk8KJ5",
+    "AppId": 1300504583,
     "Region": "ap-chengdu",
     "Version": "2023-09-01"
   },

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

@@ -250,192 +250,13 @@ namespace OASystem.Domain.Entities.Resource
         public int Count { get; set; }
     }
 
-    #region 行业信息
-
-    /// <summary>
-    /// 行业信息
-    /// </summary>
-    public class IndustryNode
+    public class AITaskItem
     {
-        public string Code { get; init; }
-        public string NameCn { get; init; }
-        public string NameEn { get; init; }
-        public string ParentCode { get; init; }
-        public List<IndustryNode> Children { get; init; } = new();
-        public string Keywords { get; init; }
-
-        public IndustryNode() { }
-
-        /// <summary>
-        /// 静态缓存:扁平化字典,用于 O(1) 效率查找
-        /// </summary>
-        private static readonly Dictionary<string, IndustryNode> _flatCache;
-        public static List<IndustryNode> Roots { get; }
-
-        static IndustryNode()
-        {
-            Roots = BuildInitialData();
-            // 预先扁平化所有节点,方便后续根据 Code 查找
-            _flatCache = Roots.SelectMany(GetSelfAndChildren).ToDictionary(x => x.Code);
-        }
-
-        /// <summary>
-        /// 递归获取所有节点(平铺)
-        /// </summary>
-        private static IEnumerable<IndustryNode> GetSelfAndChildren(IndustryNode node)
-        {
-            yield return node;
-            if (node.Children == null) yield break;
-            foreach (var child in node.Children.SelectMany(GetSelfAndChildren))
-                yield return child;
-        }
-
-        /// <summary>
-        /// 快速查找节点 (O(1))
-        /// </summary>
-        public static IndustryNode FindByCode(string code) =>
-            !string.IsNullOrEmpty(code) && _flatCache.TryGetValue(code, out var node) ? node : null;
-
-        /// <summary>
-        /// 初始化行业分类静态数据
-        /// </summary>
-        public static List<IndustryNode> BuildInitialData() => new()
-{
-    new() {
-        Code = "IND_MANU",
-        NameCn = "工业与制造业领域",
-        NameEn = "Industry & Manufacturing",
-        Keywords = "工业,制造,机械,装备,工厂,自动化",
-        Children = new()
-        {
-            new() { Code = "IND_MANU_01", ParentCode = "IND_MANU", NameCn = "工业与制造业领域", NameEn = "Industry & Manufacturing" }
-        }
-    },
-    new() {
-        Code = "ENERGY_RES",
-        NameCn = "能源与资源领域",
-        NameEn = "Energy & Resources",
-        Keywords = "能源,电力,煤炭,石油,天然气,矿产,新能源",
-        Children = new()
-        {
-            new() { Code = "ENERGY_RES_01", ParentCode = "ENERGY_RES", NameCn = "能源与资源领域", NameEn = "Energy & Resources" }
-        }
-    },
-    new() {
-        Code = "TRANS_LOG",
-        NameCn = "交通运输与物流领域",
-        NameEn = "Transportation & Logistics",
-        Keywords = "交通,运输,物流,港口,机场,铁路,公路,货运",
-        Children = new()
-        {
-            new() { Code = "TRANS_LOG_01", ParentCode = "TRANS_LOG", NameCn = "交通运输与物流领域", NameEn = "Transportation & Logistics" }
-        }
-    },
-    new() {
-        Code = "URBAN_RURAL",
-        NameCn = "城乡建设与规划领域",
-        NameEn = "Urban & Rural Construction & Planning",
-        Keywords = "城乡建设,规划,建筑,房地产,市政,工程",
-        Children = new()
-        {
-            new() { Code = "URBAN_RURAL_01", ParentCode = "URBAN_RURAL", NameCn = "城乡建设与规划领域", NameEn = "Urban & Rural Construction & Planning" }
-        }
-    },
-    new() {
-        Code = "ECO_ENV_WATER",
-        NameCn = "生态环境与水务领域",
-        NameEn = "Ecology, Environment & Water Affairs",
-        Keywords = "环保,生态,水务,水处理,污染治理,碳中和",
-        Children = new()
-        {
-            new() { Code = "ECO_ENV_WATER_01", ParentCode = "ECO_ENV_WATER", NameCn = "生态环境与水务领域", NameEn = "Ecology, Environment & Water Affairs" }
-        }
-    },
-    new() {
-        Code = "AGRI_FOOD",
-        NameCn = "农业与食品领域",
-        NameEn = "Agriculture & Food",
-        Keywords = "农业,种植,养殖,食品,农产品,粮食,渔业",
-        Children = new()
-        {
-            new() { Code = "AGRI_FOOD_01", ParentCode = "AGRI_FOOD", NameCn = "农业与食品领域", NameEn = "Agriculture & Food" }
-        }
-    },
-    new() {
-        Code = "FIN_TRADE",
-        NameCn = "金融与商贸领域",
-        NameEn = "Finance & Commerce",
-        Keywords = "金融,银行,保险,证券,商贸,零售,电商",
-        Children = new()
-        {
-            new() { Code = "FIN_TRADE_01", ParentCode = "FIN_TRADE", NameCn = "金融与商贸领域", NameEn = "Finance & Commerce" }
-        }
-    },
-    new() {
-        Code = "MED_HEALTH",
-        NameCn = "医药健康与康养领域",
-        NameEn = "Medicine, Health & Elderly Care",
-        Keywords = "医疗,医药,健康,康养,医院,器械,生物",
-        Children = new()
-        {
-            new() { Code = "MED_HEALTH_01", ParentCode = "MED_HEALTH", NameCn = "医药健康与康养领域", NameEn = "Medicine, Health & Elderly Care" }
-        }
-    },
-    new() {
-        Code = "CULT_TOUR_SPORT",
-        NameCn = "文化旅游与体育领域",
-        NameEn = "Culture, Tourism & Sports",
-        Keywords = "文化,旅游,体育,文创,传媒,娱乐,景区",
-        Children = new()
-        {
-            new() { Code = "CULT_TOUR_SPORT_01", ParentCode = "CULT_TOUR_SPORT", NameCn = "文化旅游与体育领域", NameEn = "Culture, Tourism & Sports" }
-        }
-    },
-    new() {
-        Code = "IT_DIGITAL",
-        NameCn = "信息科技与数字经济领域",
-        NameEn = "Information Technology & Digital Economy",
-        Keywords = "IT,科技,数字经济,软件,互联网,大数据,AI,云计算",
-        Children = new()
-        {
-            new() { Code = "IT_DIGITAL_01", ParentCode = "IT_DIGITAL", NameCn = "信息科技与数字经济领域", NameEn = "Information Technology & Digital Economy" }
-        }
-    },
-    new() {
-        Code = "EDU_TECH",
-        NameCn = "教育与科技领域",
-        NameEn = "Education & Technology",
-        Keywords = "教育,学校,培训,科研,技术,创新,学术",
-        Children = new()
-        {
-            new() { Code = "EDU_TECH_01", ParentCode = "EDU_TECH", NameCn = "教育与科技领域", NameEn = "Education & Technology" }
-        }
-    },
-    new() {
-        Code = "SOC_SERVICE",
-        NameCn = "社会服务与公共管理领域",
-        NameEn = "Social Services & Public Administration",
-        Keywords = "社会服务,公共管理,政府,民政,社区,公益",
-        Children = new()
-        {
-            new() { Code = "SOC_SERVICE_01", ParentCode = "SOC_SERVICE", NameCn = "社会服务与公共管理领域", NameEn = "Social Services & Public Administration" }
-        }
-    },
-    new() {
-        Code = "OTHER_KEY",
-        NameCn = "其他重点领域(应急,地质勘察,检测,知识产权)",
-        NameEn = "Other Key Fields",
-        Keywords = "应急,地质勘察,检测,知识产权,认证,标准",
-        Children = new()
-        {
-            new() { Code = "OTHER_KEY_01", ParentCode = "OTHER_KEY", NameCn = "其他重点领域(应急,地质勘察,检测,知识产权)", NameEn = "Other Key Fields" }
-        }
-    }
-};
+        public string Region { get; set; }     // 如 "North America"
+        public string Industry { get; set; }   // 如 "Software"
+        public string Scale { get; set; }      // 如 "Large"
     }
 
-    #endregion
-
     #region 单位规模信息
 
     /// <summary>