using System.Collections.Generic;
using System.IO;
using MotionFramework;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using UnityEngine;
namespace DefaultNamespace
{
///
/// 任务书信息类,用于存储解析后的任务书字段数据
/// 完全动态,不预定义任何固定字段
///
[System.Serializable]
public class TaskBookInfo
{
///
/// 字段映射字典,存储所有解析出的字段名和对应值
///
public Dictionary FieldMap { get; set; } = new Dictionary();
///
/// 原始任务书字符串
///
public string OriginalText { get; set; } = string.Empty;
///
/// 根据字段名获取对应的值
///
/// 字段名称
/// 对应的值,如果不存在则返回空字符串
public string GetValue(string fieldName)
{
return FieldMap.TryGetValue(fieldName, out string value) ? value : string.Empty;
}
///
/// 检查是否包含指定字段
///
/// 字段名称
/// 是否包含该字段
public bool HasField(string fieldName)
{
return FieldMap.ContainsKey(fieldName);
}
///
/// 获取所有字段名
///
/// 字段名集合
public IEnumerable GetAllFieldNames()
{
return FieldMap.Keys;
}
///
/// 获取所有字段和值的键值对
///
/// 所有字段的键值对
public IEnumerable> GetAllFields()
{
return FieldMap;
}
///
/// 清空所有字段数据
///
public void Clear()
{
FieldMap.Clear();
OriginalText = string.Empty;
}
}
///
/// 用于存储全局的考试相关信息以及其他可能的全局数据。
///
public class GlobalDataStorage : ModuleSingleton, IModule
{
///
/// Info文件,前端传过来的
///
public ExamInfo ExamInfo = new ExamInfo();
///
/// Info文件,前端传过来的
///
public string ExamName { get; set; }
public ApiResponse ExamData;
///
/// 任务书信息,存储解析后的任务书字段数据
///
public TaskBookInfo TaskBook { get; set; } = new TaskBookInfo();
///
/// 任务书信息,存储解析后的任务书字段数据
///
public object materialTaskObj = null;
///
/// 大类题目
///
public string bigName;
public List materialCheckInfoList = new List();
///
/// 获取任务书
///
///
public string GetTaskBook()
{
return TaskBook.OriginalText;
}
///
/// 根据字段名获取任务书中的值
///
/// 字段名称
/// 对应的值,如果不存在则返回空字符串
public string GetTaskBookValue(string fieldName)
{
return TaskBook.GetValue(fieldName);
}
///
/// 检查任务书是否包含指定字段
///
/// 字段名称
/// 是否包含该字段
public bool HasTaskBookField(string fieldName)
{
return TaskBook.HasField(fieldName);
}
///
/// 获取物料编码
///
/// 物料编码
public string GetMaterialCode()
{
return GetTaskBookValue("物料编码");
}
///
/// 获取物料描述
///
/// 物料描述
public string GetMaterialDescription()
{
return GetTaskBookValue("物料描述");
}
///
/// 获取工厂代码
///
/// 工厂代码
public string GetFactoryCode()
{
return GetTaskBookValue("工厂代码");
}
///
/// 获取批次号
///
/// 批次号
public string GetBatchNumber()
{
return GetTaskBookValue("批次");
}
///
/// 获取收入数量
///
/// 收入数量
public string GetIncomeQuantity()
{
return GetTaskBookValue("收入数量");
}
///
/// 获取台数(从"已将X台"中提取的数字)
///
/// 台数
public string GetQuantity()
{
return GetTaskBookValue("台");
}
///
/// 获取日期
///
/// 日期
public string GetDate()
{
return GetTaskBookValue("日期");
}
///
/// 获取货物交接单号
///
/// 货物交接单号
public string GetHandoverDocument()
{
return GetTaskBookValue("货物交接单");
}
///
/// 获取过账日期前
///
/// 过账日期前
public string GetPostingDateBefore()
{
return GetTaskBookValue("过账日期前");
}
///
/// 获取过账日期后
///
/// 过账日期后
public string GetPostingDateAfter()
{
return GetTaskBookValue("过账日期后");
}
///
/// 获取仓库号
///
/// 过账日期后
public string GetCangKuHao()
{
return GetTaskBookValue("仓库号");
}
///
/// 获取仓位信息
///
/// 仓位信息,如F01-010101
public string GetShelfPosition()
{
// 优先获取货架区信息
string shelfArea = GetTaskBookValue("货架区");
if (!string.IsNullOrEmpty(shelfArea))
{
return shelfArea;
}
// 其次获取仓位信息
string position = GetTaskBookValue("仓位");
if (!string.IsNullOrEmpty(position))
{
return position;
}
// 最后获取仓位号信息
string positionNumber = GetTaskBookValue("仓位号");
if (!string.IsNullOrEmpty(positionNumber))
{
return positionNumber;
}
return string.Empty;
}
///
/// 智能字段映射字典,处理字段名的模糊匹配
///
private readonly Dictionary _fieldMapping = new Dictionary
{
// 完全匹配
{"物料编码", "物料编码"},
{"物料描述", "物料描述"},
{"工厂代码", "工厂代码"},
{"批次", "批次"},
{"库存地点", "库存地点"},
{"库管员", "库管员"},
{"仓库主管", "仓库主管"},
{"物资公司签字", "物资公司签字"},
{"单位签收人", "单位签收人"},
{"供应商交付人", "供应商交付人"},
{"发货方", "发货方"},
{"收货方", "收货方"},
{"收入数量", "收入数量"},
{"结存数量", "结存数量"},
{"发出数量", "发出数量"},
{"期初库存数量", "期初库存数量"},
{"台", "台"},
{"套", "套"},
{"组", "组"},
{"米", "米"},
{"千米", "千米"},
{"只", "只"},
{"片", "片"},
{"付", "付"},
{"日期", "日期"},
{"货物交接单", "货物交接单"},
{"过账起始时间", "过账起始时间"},
{"过账结束时间", "过账结束时间"},
// {"货架区", "货架区"},
// {"仓位", "仓位"},
// {"仓位号", "仓位号"},
// 模糊匹配
{"批次号", "批次"},
{"物料编号", "物料编码"},
{"物资编码", "物料编码"},
{"物资描述", "物料描述"},
{"工厂编号", "工厂代码"},
{"库存位置", "库存地点"},
{"仓库管理员", "库管员"},
{"仓库负责人", "仓库主管"},
{"物资公司负责人", "物资公司签字"},
{"签收人", "单位签收人"},
{"交付人", "供应商交付人"},
{"发货人", "发货方"},
{"收货人", "收货方"},
{"入库数量", "收入数量"},
{"库存数量", "结存数量"},
{"出库数量", "发出数量"},
{"初始库存", "期初库存数量"},
{"已交付数量", "台"},
{"交付台数", "台"},
{"交接单号", "货物交接单"},
{"过账开始日期", "过账日期前"},
{"过账结束日期", "过账日期后"},
{"过账日期开始", "过账日期前"},
{"过账日期结束", "过账日期后"},
{"货架位置", "货架区"},
{"存储位置", "仓位"},
{"位置编号", "仓位号"},
{"上架仓位", "上架仓位"},
{"仓库号", "仓库号"},
};
///
/// 根据字段名获取对应的任务书值,支持模糊匹配
///
/// 字段名称
/// 对应的值,如果不存在则返回空字符串
public string GetTaskBookValueByMapping(string fieldName)
{
// Debug.Log($"尝试获取字段值: {fieldName}");
// 首先尝试直接匹配
if (_fieldMapping.ContainsKey(fieldName))
{
string mappedField = _fieldMapping[fieldName];
string value = GetTaskBookValue(mappedField);
Debug.Log($"字段映射成功: {fieldName} -> {mappedField} = {value}");
return value;
}
// 如果没有找到映射,尝试直接获取
string directValue = GetTaskBookValue(fieldName);
Debug.Log($"直接获取字段值: {fieldName} = {directValue}");
return directValue;
}
///
/// 更新JSON字符串中的JudgmentQuestions字段值
///
/// 原始JSON字符串
/// 更新后的JSON字符串
public string UpdateJsonWithTaskBookValues(string jsonString)
{
// 输入参数验证
if (string.IsNullOrEmpty(jsonString))
{
Debug.LogWarning("JSON字符串为空,无法更新");
return jsonString;
}
try
{
Debug.Log("开始更新JSON中的JudgmentQuestions字段值...");
// 解析JSON
JArray jsonArray = JArray.Parse(jsonString);
// 验证JSON数组是否为空
if (jsonArray == null || jsonArray.Count == 0)
{
Debug.LogWarning("JSON数组为空或无效,无法更新");
return jsonString;
}
int updatedCount = 0;
// 遍历所有步骤
foreach (JObject step in jsonArray)
{
// 验证步骤对象是否有效
if (step == null) continue;
// 检查步骤是否包含Actions数组
if (step["Actions"] != null && step["Actions"] is JArray actions)
{
// 验证Actions数组是否为空
if (actions.Count == 0) continue;
// 遍历所有动作
foreach (JObject action in actions)
{
// 验证动作对象是否有效
if (action == null) continue;
// 检查动作是否包含JudgmentQuestions且不为null
if (action["JudgmentQuestions"] != null && action["JudgmentQuestions"] is JArray judgmentQuestions)
{
// 验证判断题数组是否为空
if (judgmentQuestions.Count == 0) continue;
// 遍历所有判断题
foreach (JObject question in judgmentQuestions)
{
// 验证问题对象是否有效
if (question == null) continue;
// 安全地获取问题文本和正确答案
if (question["Question"] != null && question["CorrectAnswer"] != null)
{
string questionText = question["Question"].ToString();
string currentAnswer = question["CorrectAnswer"].ToString();
// 验证问题文本和答案是否为空
if (string.IsNullOrEmpty(questionText) || string.IsNullOrEmpty(currentAnswer))
{
Debug.LogWarning($"跳过无效的问题或答案: Question='{questionText}', Answer='{currentAnswer}'");
continue;
}
// 获取对应的任务书值
string taskBookValue = GetTaskBookValueByMapping(questionText);
if (!string.IsNullOrEmpty(taskBookValue))
{
// 更新CorrectAnswer
question["CorrectAnswer"] = taskBookValue;
updatedCount++;
Debug.Log($"更新字段: {questionText} = {taskBookValue} (原值: {currentAnswer})");
}
else
{
// Debug.Log($"未找到字段对应的任务书值: {questionText}");
}
}
}
}
}
}
}
string updatedJson = jsonArray.ToString(Formatting.None);
Debug.Log($"JSON更新完成,共更新了 {updatedCount} 个字段");
return updatedJson;
}
catch (System.Exception ex)
{
Debug.LogError($"更新JSON时发生错误: {ex.Message}");
Debug.LogError($"错误堆栈: {ex.StackTrace}");
return jsonString; // 返回原始字符串
}
}
///
/// 设置任务书信息
///
/// 任务书原始文本
public void SetTaskBook(string taskBookText)
{
TaskBook.Clear();
TaskBook.OriginalText = taskBookText;
ParseTaskBook(taskBookText);
}
///
/// 解析任务书文本,智能提取各种字段信息
///
/// 任务书文本
private void ParseTaskBook(string taskBookText)
{
if (string.IsNullOrEmpty(taskBookText))
{
Debug.LogWarning("任务书文本为空,无法解析");
return;
}
Debug.Log("开始智能解析任务书文本...");
// 定义字段匹配模式
var fieldPatterns = new Dictionary
{
// 物料相关信息
{"物料编码", @"物料编码[::]\s*([A-Za-z0-9]+)"},
{"物料描述", @"(([^)]+))|物料描述[::]\s*([^,。;:,.;:\n\r)]+?))"},
// 工厂和批次信息
{"工厂代码", @"工厂代码[::]?\s*([A-Za-z0-9*]+)"},
{"批次", @"批次[::]?\s*([A-Za-z0-9]+)"},
// 库存地点
{"库存地点", @"库存地点[::]\s*[^(]*(([A-Za-z0-9]+))"},
// 人员信息
{"库管员", @"库管员[::]\s*([^,。;:,.;:]+)"},
{"仓库主管", @"仓库主管[::]\s*([^,。;:,.;:]+)"},
{"物资公司签字", @"物资公司签字[::]\s*([^,。;:,.;:]+)"},
{"单位签收人", @"单位签收人[::]\s*([^,。;:,.;:]+)"},
{"供应商交付人", @"供应商交付人[::]\s*([^,。;:,.;:]+)"},
{"发货方", @"发货方[::]\s*([^,。;:,.;:]+)"},
{"收货方", @"收货方[::]\s*([^,。;:,.;:]+)"},
// 数量信息
{"收入数量", @"收入数量[::]\s*(\d+)"},
{"结存数量", @"结存数量[::]\s*(\d+)"},
{"发出数量", @"发出数量[::]\s*(\d+)"},
{"期初库存数量", @"期初库存数量[::]\s*(\d+)"},
{"台", @"已将(\d+)台"},
{"套", @"已将(\d+)套"},
{"组", @"已将(\d+)组"},
{"米", @"已将(\d+)米"},
{"千米", @"已将(\d+)千米"},
{"只", @"已将(\d+)只"},
{"片", @"已将(\d+)片"},
{"付", @"已将(\d+)付"},
// 日期信息
{"日期", @"日期[为]?\s*(\d{4}\.\d{2}\.\d{2})"},
{"过账起始时间", @"过账日期前[::]\s*(\d{4}\.\d{2}月\.\d{2})"},
{"过账结束时间", @"过账日期后[::]\s*(\d{4}\.\d{2}月\.\d{2})"},
// 单据信息
{"货物交接单", @"货物交接单[::]\s*([A-Za-z0-9]+)"},
{"仓库号", @"仓库号[::]?\s*([A-Za-z0-9]+)"},
// //仓位号
// {"货架区", @"货架区[::]\s*([A-Za-z0-9\-]+)"},
// {"仓位", @"仓位[::]\s*([A-Za-z0-9\-]+)"},
// {"仓位号", @"仓位号[::]\s*([A-Za-z0-9\-]+)"},
// 复合格式解析 - 支持"货架区F01-010101仓位"等格式
// {"上架仓位", @"货架区([A-Za-z0-9\-]+)仓位"},
// 直接匹配仓位编号格式 F01-010101
{"上架仓位", @"([A-Z][0-9]{2}-[0-9]{6})"},
};
int parsedFieldsCount = 0;
// 遍历所有字段模式进行匹配
foreach (var pattern in fieldPatterns)
{
string fieldName = pattern.Key;
string regexPattern = pattern.Value;
try
{
System.Text.RegularExpressions.Regex regex = new System.Text.RegularExpressions.Regex(regexPattern);
System.Text.RegularExpressions.Match match = regex.Match(taskBookText);
if (match.Success && match.Groups.Count >= 2)
{
string value = string.Empty;
// 特殊处理物料描述字段,支持两种格式的合并正则
if (fieldName == "物料描述")
{
// 检查第一个捕获组(括号格式)
if (match.Groups[1].Success && !string.IsNullOrEmpty(match.Groups[1].Value.Trim()))
{
value = match.Groups[1].Value.Trim();
Debug.Log($"成功解析字段: [物料描述] = {value} (括号格式)");
// 如果括号格式解析成功,再次解析物料描述
int materialDescIndex = value.IndexOf("物料描述:");
if (materialDescIndex >= 0)
{
string materialDescValue = value.Substring(materialDescIndex + 4); // 跳过"物料描述:"
materialDescValue = CleanValue(materialDescValue);
if (!string.IsNullOrEmpty(materialDescValue))
{
value = materialDescValue;
Debug.Log($"成功解析字段: [物料描述] = {value} (从括号格式中再次解析)");
}
}
}
// 检查第二个捕获组(冒号格式)
else if (match.Groups[2].Success && !string.IsNullOrEmpty(match.Groups[2].Value.Trim()))
{
value = match.Groups[2].Value.Trim();
Debug.Log($"成功解析字段: [物料描述] = {value} (冒号格式)");
}
}
else
{
value = match.Groups[1].Value.Trim();
}
// 清理值中的多余字符
value = CleanValue(value);
if (!string.IsNullOrEmpty(value))
{
TaskBook.FieldMap[fieldName] = value;
if (fieldName != "物料描述") // 物料描述已经在上面打印过日志了
{
Debug.Log($"成功解析字段: [{fieldName}] = {value}");
}
parsedFieldsCount++;
}
}
else
{
Debug.Log($"未找到字段: {fieldName}");
}
}
catch (System.Exception ex)
{
Debug.LogError($"解析字段 {fieldName} 时发生错误: {ex.Message}");
}
}
Debug.Log($"任务书解析完成,共成功解析出 {parsedFieldsCount} 个字段");
Debug.Log($"解析出的字段列表: {string.Join(", ", TaskBook.FieldMap.Keys)}");
}
///
/// 清理值中的多余字符
///
/// 原始值
/// 清理后的值
private string CleanValue(string value)
{
if (string.IsNullOrEmpty(value))
return value;
// 移除开头和结尾的标点符号和空格
value = value.Trim(',', '。', ';', ':', ',', '.', ';', ':', ' ', '\t', '\n', '\r');
// 处理日期格式中的"月"字符,将其替换为"."
// 例如:2024.12月.01 -> 2024.12.01
value = value.Replace("月", ".");
// 清理重复的点号
while (value.Contains(".."))
{
value = value.Replace("..", ".");
}
return value;
}
//
public void OnCreate(object createParam)
{
}
public void OnUpdate()
{
}
public void OnDestroy()
{
}
public void OnGUI()
{
}
}
}