|
|
@@ -6,8 +6,12 @@ using Aspose.Words.Saving;
|
|
|
using Aspose.Words.Tables;
|
|
|
using Humanizer;
|
|
|
using Microsoft.AspNetCore.SignalR;
|
|
|
+using Microsoft.Graph.Models;
|
|
|
using Microsoft.International.Converters.PinYinConverter;
|
|
|
+using Microsoft.Kiota.Abstractions;
|
|
|
using NodaTime;
|
|
|
+using NPOI.SS.Formula;
|
|
|
+using NPOI.SS.Formula.Functions;
|
|
|
using OASystem.API.OAMethodLib.File;
|
|
|
using OASystem.API.OAMethodLib.Hub.HubClients;
|
|
|
using OASystem.API.OAMethodLib.Hub.Hubs;
|
|
|
@@ -31,6 +35,9 @@ using System.ComponentModel.DataAnnotations;
|
|
|
using System.Data;
|
|
|
using System.IdentityModel.Tokens.Jwt;
|
|
|
using System.Security.Claims;
|
|
|
+using static Azure.Core.HttpHeader;
|
|
|
+using static QRCoder.PayloadGenerator;
|
|
|
+using static QRCoder.QRCodeGenerator;
|
|
|
|
|
|
namespace OASystem.API.OAMethodLib
|
|
|
{
|
|
|
@@ -1335,7 +1342,477 @@ namespace OASystem.API.OAMethodLib
|
|
|
}
|
|
|
#endregion
|
|
|
|
|
|
- #region 商邀AI invName 整合
|
|
|
+ #region 公务 AI
|
|
|
+
|
|
|
+ #region 提示词构建
|
|
|
+
|
|
|
+ /// <summary>
|
|
|
+ /// 构建行业匹配提示词(含预筛选逻辑)
|
|
|
+ /// <param name="entryInfo">【必填】基础配置信息</param>
|
|
|
+ /// <param name="localData">【数据源】来自 SqlSugar 查询的本地候选数据集,需包含 Region 和 NameCn 字段</param>
|
|
|
+ /// <returns>返回经过结构化处理的 Markdown 格式 Prompt 字符串</returns>
|
|
|
+ /// </summary>
|
|
|
+ public static string BuildIndustryPrompt(EntryInfo entryInfo, IEnumerable<InvitationAIInfo> localData)
|
|
|
+ {
|
|
|
+ // 业务逻辑预处理:仅保留目标国家数据,大幅节省 Token 成本
|
|
|
+ var filteredData = localData
|
|
|
+ .Where(x => entryInfo.TargetCountry.Contains(x.Region))
|
|
|
+ .Select(x => new { x.Region, x.NameCn }) // 仅提取 AI 需要的字段
|
|
|
+ .Distinct()
|
|
|
+ .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);
|
|
|
+ string sourceUnit = entryInfo.OriginUnit ?? "未知单位";
|
|
|
+ string sourceIndustry = string.Join(", ", entryInfo.Industries);
|
|
|
+
|
|
|
+ // 将提示词模板定义为常量,方便维护和查阅
|
|
|
+ string promptTemplate = @"
|
|
|
+# Role
|
|
|
+你是一位精通全球产业结构与大数据清洗的【智能匹配专家】。
|
|
|
+
|
|
|
+# Standard Industry Categories (Dynamic)
|
|
|
+请将目标单位严格归类为以下指定的行业类别:
|
|
|
+{0}
|
|
|
+*注意:若无法完全匹配,请归类至语义最接近的一项。*
|
|
|
+
|
|
|
+# Situation (Dynamic Input)
|
|
|
+- **出访单位**:{1}
|
|
|
+- **其所属行业**:{2}
|
|
|
+- **目标出访国家**:{3}
|
|
|
+
|
|
|
+# Task
|
|
|
+分析【本地待匹配数据集】,执行以下逻辑:
|
|
|
+1. **实体一致性 (Critical)**:返回结果中的 TargetUnitName 必须与输入数据集中的 NameCn 完全一致,严禁修改。
|
|
|
+2. **语义归类**:分析业务关键词,并映射至上述标准行业分类。
|
|
|
+3. **关联度计算**:计算与出访单位的业务契合度 (ConfidenceScore: 0.0-1.0)。
|
|
|
+
|
|
|
+# Rules
|
|
|
+- **输出格式**:仅返回纯 JSON 数组,严禁任何解释性文字。
|
|
|
+- **命名规范**:JSON 键名严格使用 PascalCase。
|
|
|
+
|
|
|
+# Data Source (JSON Array)
|
|
|
+{4}
|
|
|
+
|
|
|
+# Output Format (Required JSON)
|
|
|
+[
|
|
|
+ {{
|
|
|
+ ""SourceUnitName"": ""{1}"",
|
|
|
+ ""TargetUnitName"": ""必须与输入数据原样一致"",
|
|
|
+ ""TargetCountry"": ""所在国家"",
|
|
|
+ ""MatchedIndustry"": ""必须匹配标准行业分类中的原词"",
|
|
|
+ ""ConfidenceScore"": 0.00,
|
|
|
+ ""MatchReason"": ""匹配理由""
|
|
|
+ }}
|
|
|
+]
|
|
|
+";
|
|
|
+ // 填充模板并返回
|
|
|
+ return string.Format(
|
|
|
+ promptTemplate,
|
|
|
+ industryStandardStr, // {0}
|
|
|
+ sourceUnit, // {1}
|
|
|
+ sourceIndustry, // {2}
|
|
|
+ countriesStr, // {3}
|
|
|
+ jsonData // {4}
|
|
|
+ );
|
|
|
+ }
|
|
|
+
|
|
|
+ #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="countryTasks"></param>
|
|
|
+ /// <param name="entryInfo">包含规则基础信息</param>
|
|
|
+ /// <returns>最终构建的 System Prompt 字符串</returns>
|
|
|
+ public static string BuildHunyuanPrompt(List<CountryAIPormptInfo> tasks, List<AITaskItem> countryTasks, EntryInfo entryInfo)
|
|
|
+ {
|
|
|
+ // 行业信息,用于提示词硬约束
|
|
|
+ string industryEnum = string.Join("、", IndustryTree.Build().Select(x => x.NameCn).ToList());
|
|
|
+
|
|
|
+ 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.OrgLevel) && !entryInfo.OrgLevel.Equals("全部")) businessConstraints.AppendLine($" - 公司层级: {entryInfo.OrgLevel}");
|
|
|
+ if (!string.IsNullOrEmpty(entryInfo.OtherConstraints)) businessConstraints.AppendLine($" - 其他规则: {entryInfo.OtherConstraints}");
|
|
|
+ if (businessConstraints == null || businessConstraints.Length == 0) businessConstraints.AppendLine("无");
|
|
|
+
|
|
|
+ return $@"
|
|
|
+# [SYSTEM_ROLE]
|
|
|
+你是精通全球实时经贸情报的【顶级商务咨询顾问】。
|
|
|
+你具备资深 .NET 6 架构思维,输出 JSON 必须 100% 兼容强类型反序列化。遵循“无存证不输出、官网优先溯源、AB管道证伪、零虚构熔断”的最高数据纯度准则。
|
|
|
+
|
|
|
+# [CONTEXT_ANALYSIS]
|
|
|
+• 当前核查基准时间 (CurrentDate): {DateTime.Now:yyyy-MM-dd} (锁定动态年份为绝对时空锚点)
|
|
|
+• 发起单位 (OriginUnit): {entryInfo.OriginUnit}
|
|
|
+• 业务硬性约束 (BusinessConstraints): {businessConstraints}
|
|
|
+• 核心驱动配置 (CountryTasks): {JsonConvert.SerializeObject(countryTasks)}
|
|
|
+• 任务配额分配 (Tasks): {JsonConvert.SerializeObject(tasks)}
|
|
|
+
|
|
|
+# [REALITY_CHECK_RULES - 严禁虚构与存证审计标准]
|
|
|
+
|
|
|
+## 1. 企业存在性“三位一体”核验 (Anti-Hallucination)
|
|
|
+- **核心原则**:严禁推测、编造、组合不存在的企业名称。必须严格按照 `CountryTasks` 定义的区域执行检索。
|
|
|
+- **验证链条**:
|
|
|
+ 1. **官网验证**:SiteUrl 必须真实可访问,且内容与企业业务高度吻合。
|
|
|
+ 2. **管道 A (官方公示)**:必须在目标国工商注册局、证监会或经商处有备案。
|
|
|
+ 3. **管道 B (公正存证)**:必须在 LinkedIn (官方认证页)、Bloomberg 或 Crunchbase 有实时动态。
|
|
|
+- **熔断判定**:若以上三项均无法交叉证实企业真实存在性,该条目必须立即废弃。
|
|
|
+
|
|
|
+## 2. 软 404 与“FoundPage”假死内容熔断
|
|
|
+- **实质内容审计**:即便 URL 响应 200,若页面包含以下特征,必须判定为**死链**并熔断:
|
|
|
+ - **特征词**:`404 Not Found`, `Page Not Found`, `Oops`, `Seite nicht gefunden`, `foundpage`, `链接不存在`.
|
|
|
+- **主站熔断**:若 `SiteUrl` 触碰报错特征,该企业条目整体作废;若仅 `PostUrl` 触碰,则动态字段返回 `[]`。
|
|
|
+
|
|
|
+## 3. 信息溯源:官网优先与 AB 管道补位
|
|
|
+- **首要来源**:新闻 (PostUrl)、联系人 (Contact) 与邮件 (Email) 必须优先从企业官网提取。
|
|
|
+- **补位机制**:仅当官网无法获取联系信息时,允许从 AB 管道(管道B认证页)提取 {DateTime.Now.AddYears(-3).Year}-{DateTime.Now.Year} 年间的实时活跃数据。
|
|
|
+
|
|
|
+## 4. 属地物理地址强校验 (GEO_ADDRESS_STRICTNESS)
|
|
|
+- **物理属地锁定原则**:企业必须是在目标国家**实际运营、注册并拥有实体办公场所**的主体,严禁接受虚拟办公室、共享注册地址或仅用于税务/法律注册的空壳地址。
|
|
|
+- **地址真实性审计流程**:
|
|
|
+ 1. **地理一致性校验**:`Address` 字段必须位于 `CountryTasks` 指定的国家境内,且与官网“Contact / Imprint / About Us”页面披露的实体地址完全一致。
|
|
|
+ 2. **地图实体验证(AB 管道)**:必须通过 Google Maps / OpenStreetMap 等权威地理服务验证该地址对应真实建筑,且建筑内确实挂有该企业标识(或街景证据)。
|
|
|
+ 3. **虚拟地址熔断**:若地址被识别为虚拟办公、信箱服务(P.O. Box)或商业中心,该条目**整条作废**。
|
|
|
+- **输出规范**:`Address` 必须返回**可直接复制粘贴到 Google Maps、百度地图、Apple 地图等主流地图服务中进行搜索和导航的完整物理地址**。格式要求:街道地址 + 城市 + 州/省 + 邮政编码 + 国家。地址中必须包含可被地图服务准确识别的**邮政编码**。
|
|
|
+
|
|
|
+# [BUSINESS_CONSTRAINTS_SCHEMA]
|
|
|
+- **零虚构原则**:绝对禁止编造任何不存在的企业、人名、链接或动态。
|
|
|
+- **行业约束**:Industry 必须严格锁定在业务定义的范围内,严禁跨类延伸。
|
|
|
+- **规模匹配**:Scale 必须严格匹配“单位规模”集合定义。
|
|
|
+- **英文命名清洗规则 (NAMING_CONVENTION_EN_CLEAN)**:在 `NameEn` 字段中,**严禁出现任何法律实体后缀标识**。包括但不限于:`PTY LTD`, `LTD`, `LIMITED`, `LLC`, `INC`, `CORP`, `PLC`, `GMBH`, `AG`, `SAS`, `SARL`, `BV`, `NV` 等。`NameEn` 应仅保留企业**核心品牌名或商号 (Trading Name)**,确保与官网首页主 Title 保持一致。若清洗后 `NameEn` 为空或仅剩通用词,该条目视为**无效命名并整体废弃**。
|
|
|
+
|
|
|
+# [QUOTA_SCHEDULING - 动态再分配算法]
|
|
|
+- **名额平移**:若 `CountryTasks` 指定的某国家因“官网失效/无法证伪”导致有效条目不足,允许实际输出数 < 理论配额。
|
|
|
+- **禁止凑数**:名额自动向质量更高、官网更活跃的国家转移,严禁为了填满 JSON 而降低审计标准。
|
|
|
+
|
|
|
+# [THOUGHT_PROCESS_LOGIC]
|
|
|
+1. 解析 `CountryTasks` 与 `BusinessConstraints` -> 2. 执行 {DateTime.Now.Year} 实时检索 -> 3. **执行存在性三位一体核验(证伪熔断)** -> 4. **扫描官网内容(识别并过滤软404)** -> 5. **属地物理地址强校验** -> 6. **英文命名清洗** -> 7. **以官网为核心、AB管道为备份提取字段** -> 8. 生成纯净 JSON。
|
|
|
+
|
|
|
+# [STRICT_DATA_CONTRACT]
|
|
|
+属性命名遵循 PascalCase,禁止新增字段:
|
|
|
+[
|
|
|
+ {{
|
|
|
+ ""Region"": ""string"",
|
|
|
+ ""Industry"": ""string"",
|
|
|
+ ""Scale"": ""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""
|
|
|
+ }}
|
|
|
+]
|
|
|
+
|
|
|
+# [HUNYUAN_OUTPUT_GUARDRAILS]
|
|
|
+你是一个严格的 JSON 生成器。
|
|
|
+1. 最高禁令:绝对禁止编造任何不存在的企业、人名、链接或动态。
|
|
|
+2. 输出洁癖:不输出 Markdown 标记、不输出任何解释文字或思考过程。
|
|
|
+3. 边界控制:首字符 [,末字符 ]。结果为空输出 []。
|
|
|
+
|
|
|
+# [EXECUTION]
|
|
|
+立即执行:以动态年份为锚点,执行严苛的企业真实性审计与软 404 熔断逻辑,严禁虚构任何信息,按契约输出纯净 JSON。
|
|
|
+";
|
|
|
+ }
|
|
|
+
|
|
|
+ #endregion
|
|
|
+
|
|
|
+ #region 基础数据 整合
|
|
|
|
|
|
/// <summary>
|
|
|
/// 商邀AI invName 整合
|
|
|
@@ -1357,13 +1834,13 @@ namespace OASystem.API.OAMethodLib
|
|
|
// 先进行去重逻辑处理
|
|
|
var distinctQuery = _sqlSugar.Queryable(unionQuery)
|
|
|
.PartitionBy(it => it.Name)
|
|
|
- .OrderByDescending(it => it.SortTime)
|
|
|
+ .OrderByDescending(it => it.SortTime)
|
|
|
.Select(it => it);
|
|
|
|
|
|
// 将去重后的结果包装,再进行全局
|
|
|
- return await _sqlSugar.Queryable(distinctQuery)
|
|
|
- .OrderByDescending(it => it.Source)
|
|
|
- .OrderByDescending(it => it.SortTime)
|
|
|
+ return await _sqlSugar.Queryable(distinctQuery)
|
|
|
+ .OrderByDescending(it => it.Source)
|
|
|
+ .OrderByDescending(it => it.SortTime)
|
|
|
.ToListAsync();
|
|
|
}
|
|
|
|
|
|
@@ -1431,6 +1908,8 @@ namespace OASystem.API.OAMethodLib
|
|
|
|
|
|
#endregion
|
|
|
|
|
|
+ #endregion
|
|
|
+
|
|
|
#region 团组汇率
|
|
|
|
|
|
/// <summary>
|