1349 lines
56 KiB
C#
1349 lines
56 KiB
C#
using System;
|
||
using System.Collections.Generic;
|
||
using System.Linq;
|
||
using DefaultNamespace.ProcessMode;
|
||
using Framework.Manager;
|
||
using Framework.ProcessMode;
|
||
using MotionFramework;
|
||
using TMPro;
|
||
using UnityEngine;
|
||
using UnityEngine.UI;
|
||
using ProcessMode = DefaultNamespace.ProcessMode.ProcessMode;
|
||
|
||
namespace Zion.Scripts.ERP.库存物资查询报表
|
||
{
|
||
public class LedgerTransferPostingManager : MonoBehaviour
|
||
{
|
||
public TMP_InputField[] batchs; //批次输入框数组
|
||
public TMP_InputField[] materialCodes; // 物料编码输入框数组
|
||
public TMP_InputField[] storageLocations; // 库存地点输入框数组
|
||
public TMP_InputField[] factories; // 工厂输入框数组
|
||
public TMP_InputField[] movementReasons; // 移动原因输入框数组
|
||
public TMP_InputField[] quantities; // 数量输入框数组
|
||
|
||
|
||
public TMP_InputField[] kucundidian; // 数量输入框数组
|
||
public TMP_InputField[] picichuanshu; // 数量输入框数组
|
||
|
||
|
||
public TMP_Dropdown quantitiesDropdown;
|
||
public TMP_Dropdown quantitiesDropdown2;
|
||
|
||
|
||
public Button queryButton;
|
||
public Button jianchaButton;
|
||
public TMP_Text titleText;
|
||
|
||
public bool onlyFirst = false;
|
||
public AutoHideScript autoHideScript;
|
||
|
||
// 输入顺序验证相关变量
|
||
private bool isMaterialCodeCompleted = false; // 物料编码是否完成
|
||
private bool isStorageLocationCompleted = false; // 库存地点是否完成
|
||
private bool isFactoryCompleted = false; // 工厂是否完成
|
||
private bool isInputOrderValid = true; // 输入顺序是否有效
|
||
|
||
// 模式管理相关变量
|
||
private ProcessMode _cachedCurrentMode; // 缓存的当前模式
|
||
|
||
// 每行标准答案(索引0对应"1行/1号")- 从框架动态获取
|
||
private string[] materialCodeAnswers = new string[0];
|
||
private string[] storageLocationAnswers = new string[0];
|
||
private string[] factoryAnswers = new string[0];
|
||
private string[] movementReasonAnswers = new string[0];
|
||
private string[] quantityAnswers = new string[0];
|
||
private string[] batchAnswers = new string[0];
|
||
|
||
// 无序绑定:行 -> 答案索引(确定该行属于"1号/2号/...")
|
||
private readonly Dictionary<int, int> rowToAnswerIndex = new Dictionary<int, int>();
|
||
|
||
// 字段验证状态跟踪:记录每个字段是否已经通过验证并触发过向导(用于避免重复触发)
|
||
// 键:(行索引, 字段标签),值:是否已经触发过向导
|
||
private readonly Dictionary<(int rowIndex, string fieldLabel), bool> fieldValidationStates = new Dictionary<(int, string), bool>();
|
||
|
||
// 已完成验证的字段集合:验证通过并触发向导后,不再跟踪这些字段的变化
|
||
private readonly HashSet<(int rowIndex, string fieldLabel)> completedFields = new HashSet<(int, string)>();
|
||
|
||
/// <summary>
|
||
/// 获取当前是否为教学模式
|
||
/// </summary>
|
||
private bool IsTeachingMode => _cachedCurrentMode == ProcessMode.教学模式;
|
||
|
||
/// <summary>
|
||
/// 获取当前是否为考核模式
|
||
/// </summary>
|
||
private bool IsAssessmentMode => _cachedCurrentMode == ProcessMode.考核模式;
|
||
|
||
private void Start()
|
||
{
|
||
queryButton.onClick.AddListener(() => OnQueryButtonClicked());
|
||
jianchaButton.onClick.AddListener(delegate
|
||
{
|
||
for (int i = 0; i < storageLocations.Length; i++)
|
||
{
|
||
kucundidian[i].text = storageLocations[i].text;
|
||
}
|
||
|
||
for (int i = 0; i < batchs.Length; i++)
|
||
{
|
||
picichuanshu[i].text = batchs[i].text;
|
||
}
|
||
|
||
|
||
autoHideScript.ShowObject("已检查");
|
||
TutorialGuideManager.Instance.TriggerNextGuide(jianchaButton.name);
|
||
});
|
||
|
||
// 初始化输入验证系统
|
||
InitializeInputValidation();
|
||
}
|
||
|
||
|
||
/// <summary>
|
||
/// 初始化下拉框默认选择
|
||
/// </summary>
|
||
private void InitializeDropdowns()
|
||
{
|
||
// 初始化quantitiesDropdown默认选择第一个选项
|
||
if (quantitiesDropdown != null && quantitiesDropdown.options.Count > 0)
|
||
{
|
||
quantitiesDropdown.value = 0;
|
||
Debug.Log($"quantitiesDropdown默认选择: {quantitiesDropdown.options[0].text}");
|
||
}
|
||
else
|
||
{
|
||
Debug.LogWarning("quantitiesDropdown为null或没有选项");
|
||
}
|
||
|
||
// 初始化quantitiesDropdown2默认选择第一个选项
|
||
if (quantitiesDropdown2 != null && quantitiesDropdown2.options.Count > 0)
|
||
{
|
||
quantitiesDropdown2.value = 0;
|
||
Debug.Log($"quantitiesDropdown2默认选择: {quantitiesDropdown2.options[0].text}");
|
||
}
|
||
else
|
||
{
|
||
Debug.LogWarning("quantitiesDropdown2为null或没有选项");
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// 初始化输入验证系统
|
||
/// </summary>
|
||
private void InitializeInputValidation()
|
||
{
|
||
// 缓存当前模式
|
||
CacheCurrentMode();
|
||
|
||
// 从流程框架获取答案并解析
|
||
LoadAnswersFromFramework();
|
||
|
||
// 为所有输入框添加值变化监听
|
||
AddInputFieldListeners();
|
||
|
||
// 初始化输入框状态
|
||
UpdateInputFieldStates();
|
||
}
|
||
|
||
/// <summary>
|
||
/// 从流程框架获取当前动作的答案并解析
|
||
/// </summary>
|
||
private void LoadAnswersFromFramework()
|
||
{
|
||
try
|
||
{
|
||
var processManager = MotionEngine.GetModule<ProcessManager>();
|
||
if (processManager == null)
|
||
{
|
||
Debug.LogWarning("ProcessManager未找到,使用默认空答案");
|
||
return;
|
||
}
|
||
|
||
// 通过反射获取当前动作
|
||
var currentStepIndexField = typeof(ProcessManager).GetField("_currentStepIndex",
|
||
System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance);
|
||
var currentActionIndexField = typeof(ProcessManager).GetField("_currentActionIndex",
|
||
System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance);
|
||
|
||
if (currentStepIndexField != null && currentActionIndexField != null)
|
||
{
|
||
int currentStepIndex = (int)currentStepIndexField.GetValue(processManager);
|
||
int currentActionIndex = (int)currentActionIndexField.GetValue(processManager);
|
||
|
||
var currentProcessCollection = processManager.CurrentProcessCollection;
|
||
if (currentStepIndex >= 0 && currentStepIndex < currentProcessCollection.Steps.Count)
|
||
{
|
||
var currentStep = currentProcessCollection.Steps[currentStepIndex];
|
||
if (currentActionIndex >= 0 && currentActionIndex < currentStep.Actions.Count)
|
||
{
|
||
var currentAction = currentStep.Actions[currentActionIndex];
|
||
|
||
// 解析JudgmentQuestions
|
||
if (currentAction.JudgmentQuestions != null && currentAction.JudgmentQuestions.Count > 0)
|
||
{
|
||
ParseAnswersFromJudgmentQuestions(currentAction.JudgmentQuestions);
|
||
Debug.Log("从流程框架成功加载答案");
|
||
return;
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
Debug.LogWarning("无法从流程框架获取当前动作的JudgmentQuestions");
|
||
}
|
||
catch (System.Exception ex)
|
||
{
|
||
Debug.LogError($"从流程框架加载答案时发生错误: {ex.Message}");
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// 解析JudgmentQuestions并构建答案数组
|
||
/// </summary>
|
||
private void ParseAnswersFromJudgmentQuestions(List<JudgmentQuestionConfig> questions)
|
||
{
|
||
// 初始化字典来存储每组的答案
|
||
Dictionary<string, Dictionary<int, string>> answerGroups = new Dictionary<string, Dictionary<int, string>>();
|
||
answerGroups["物料编码"] = new Dictionary<int, string>();
|
||
answerGroups["库存地点"] = new Dictionary<int, string>();
|
||
answerGroups["工厂"] = new Dictionary<int, string>();
|
||
answerGroups["移动原因"] = new Dictionary<int, string>();
|
||
answerGroups["数量"] = new Dictionary<int, string>();
|
||
answerGroups["批次"] = new Dictionary<int, string>();
|
||
|
||
foreach (var question in questions)
|
||
{
|
||
if (string.IsNullOrEmpty(question.Question) || string.IsNullOrEmpty(question.CorrectAnswer))
|
||
continue;
|
||
|
||
// 解析Question格式:如"物料编码1"、"库存地点2"等
|
||
// 提取类型和索引
|
||
foreach (var groupKey in answerGroups.Keys)
|
||
{
|
||
if (question.Question.Contains(groupKey))
|
||
{
|
||
// 提取数字(索引)
|
||
string numberStr = question.Question.Replace(groupKey, "").Trim();
|
||
if (int.TryParse(numberStr, out int index))
|
||
{
|
||
// 索引转换为数组索引(1->0, 2->1, 3->2)
|
||
int arrayIndex = index - 1;
|
||
if (arrayIndex >= 0)
|
||
{
|
||
answerGroups[groupKey][arrayIndex] = question.CorrectAnswer;
|
||
}
|
||
}
|
||
break;
|
||
}
|
||
}
|
||
}
|
||
|
||
// 为每个类型独立计算其最大索引(允许不同类型有不同的数量)
|
||
int GetMaxIndexForGroup(Dictionary<int, string> group)
|
||
{
|
||
if (group.Count == 0) return 0;
|
||
return group.Keys.Max() + 1;
|
||
}
|
||
|
||
// 为每个类型构建对应长度的数组
|
||
int materialCodeMaxIndex = GetMaxIndexForGroup(answerGroups["物料编码"]);
|
||
int storageLocationMaxIndex = GetMaxIndexForGroup(answerGroups["库存地点"]);
|
||
int factoryMaxIndex = GetMaxIndexForGroup(answerGroups["工厂"]);
|
||
int movementReasonMaxIndex = GetMaxIndexForGroup(answerGroups["移动原因"]);
|
||
int quantityMaxIndex = GetMaxIndexForGroup(answerGroups["数量"]);
|
||
int batchMaxIndex = GetMaxIndexForGroup(answerGroups["批次"]);
|
||
|
||
// 构建答案数组(每个类型只创建实际需要的长度)
|
||
if (materialCodeMaxIndex > 0)
|
||
{
|
||
materialCodeAnswers = new string[materialCodeMaxIndex];
|
||
for (int i = 0; i < materialCodeMaxIndex; i++)
|
||
{
|
||
materialCodeAnswers[i] = answerGroups["物料编码"].ContainsKey(i) ? answerGroups["物料编码"][i] : "";
|
||
}
|
||
}
|
||
|
||
if (storageLocationMaxIndex > 0)
|
||
{
|
||
storageLocationAnswers = new string[storageLocationMaxIndex];
|
||
for (int i = 0; i < storageLocationMaxIndex; i++)
|
||
{
|
||
storageLocationAnswers[i] = answerGroups["库存地点"].ContainsKey(i) ? answerGroups["库存地点"][i] : "";
|
||
}
|
||
}
|
||
|
||
if (factoryMaxIndex > 0)
|
||
{
|
||
factoryAnswers = new string[factoryMaxIndex];
|
||
for (int i = 0; i < factoryMaxIndex; i++)
|
||
{
|
||
factoryAnswers[i] = answerGroups["工厂"].ContainsKey(i) ? answerGroups["工厂"][i] : "";
|
||
}
|
||
}
|
||
|
||
if (movementReasonMaxIndex > 0)
|
||
{
|
||
movementReasonAnswers = new string[movementReasonMaxIndex];
|
||
for (int i = 0; i < movementReasonMaxIndex; i++)
|
||
{
|
||
movementReasonAnswers[i] = answerGroups["移动原因"].ContainsKey(i) ? answerGroups["移动原因"][i] : "";
|
||
}
|
||
}
|
||
|
||
if (quantityMaxIndex > 0)
|
||
{
|
||
quantityAnswers = new string[quantityMaxIndex];
|
||
for (int i = 0; i < quantityMaxIndex; i++)
|
||
{
|
||
quantityAnswers[i] = answerGroups["数量"].ContainsKey(i) ? answerGroups["数量"][i] : "";
|
||
}
|
||
}
|
||
|
||
if (batchMaxIndex > 0)
|
||
{
|
||
batchAnswers = new string[batchMaxIndex];
|
||
for (int i = 0; i < batchMaxIndex; i++)
|
||
{
|
||
batchAnswers[i] = answerGroups["批次"].ContainsKey(i) ? answerGroups["批次"][i] : "";
|
||
}
|
||
}
|
||
|
||
Debug.Log($"解析答案完成 - 物料编码({materialCodeMaxIndex}个): [{string.Join(", ", materialCodeAnswers)}], " +
|
||
$"库存地点({storageLocationMaxIndex}个): [{string.Join(", ", storageLocationAnswers)}], " +
|
||
$"工厂({factoryMaxIndex}个): [{string.Join(", ", factoryAnswers)}], " +
|
||
$"移动原因({movementReasonMaxIndex}个): [{string.Join(", ", movementReasonAnswers)}], " +
|
||
$"数量({quantityMaxIndex}个): [{string.Join(", ", quantityAnswers)}], " +
|
||
$"批次({batchMaxIndex}个): [{string.Join(", ", batchAnswers)}]");
|
||
}
|
||
|
||
/// <summary>
|
||
/// 缓存当前模式
|
||
/// </summary>
|
||
private void CacheCurrentMode()
|
||
{
|
||
try
|
||
{
|
||
var processManager = MotionEngine.GetModule<ProcessManager>();
|
||
if (processManager != null)
|
||
{
|
||
_cachedCurrentMode = processManager._currentMode;
|
||
Debug.Log($"缓存当前模式: {_cachedCurrentMode}");
|
||
}
|
||
else
|
||
{
|
||
Debug.LogWarning("ProcessManager未找到,使用默认模式");
|
||
_cachedCurrentMode = ProcessMode.教学模式; // 默认模式
|
||
}
|
||
}
|
||
catch (System.Exception ex)
|
||
{
|
||
Debug.LogError($"获取当前模式时发生错误: {ex.Message}");
|
||
_cachedCurrentMode = ProcessMode.教学模式; // 默认模式
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// 为所有输入框添加值变化监听
|
||
/// </summary>
|
||
private void AddInputFieldListeners()
|
||
{
|
||
// 为物料编码输入框添加监听(带行索引验证)
|
||
for (int i = 0; i < materialCodes.Length; i++)
|
||
{
|
||
int rowIndex = i;
|
||
var inputField = materialCodes[i];
|
||
if (inputField == null) continue;
|
||
inputField.onValueChanged.AddListener((value) =>
|
||
{
|
||
OnMaterialCodeChanged(value);
|
||
ValidateField(materialCodes, materialCodeAnswers, rowIndex, "物料编码");
|
||
});
|
||
}
|
||
|
||
// 为库存地点输入框添加监听(带行索引验证)
|
||
for (int i = 0; i < storageLocations.Length; i++)
|
||
{
|
||
int rowIndex = i;
|
||
var inputField = storageLocations[i];
|
||
if (inputField == null) continue;
|
||
inputField.onValueChanged.AddListener((value) =>
|
||
{
|
||
OnStorageLocationChanged(value);
|
||
ValidateField(storageLocations, storageLocationAnswers, rowIndex, "库存地点");
|
||
});
|
||
}
|
||
|
||
// 为工厂输入框添加监听(带行索引验证)
|
||
for (int i = 0; i < factories.Length; i++)
|
||
{
|
||
int rowIndex = i;
|
||
var inputField = factories[i];
|
||
if (inputField == null) continue;
|
||
inputField.onValueChanged.AddListener((value) =>
|
||
{
|
||
OnFactoryChanged(value);
|
||
ValidateField(factories, factoryAnswers, rowIndex, "工厂");
|
||
});
|
||
}
|
||
|
||
// 为批次输入框添加监听(包括焦点控制与带行索引验证)
|
||
for (int i = 0; i < batchs.Length; i++)
|
||
{
|
||
int rowIndex = i;
|
||
var inputField = batchs[i];
|
||
if (inputField == null) continue;
|
||
inputField.onValueChanged.AddListener((value) =>
|
||
{
|
||
OnBatchChanged(value);
|
||
if (isInputOrderValid)
|
||
{
|
||
ValidateField(batchs, batchAnswers, rowIndex, "批次");
|
||
}
|
||
});
|
||
|
||
// 在教学模式下添加焦点控制
|
||
if (IsTeachingMode)
|
||
{
|
||
inputField.onSelect.AddListener((value) => OnBatchFieldSelected(inputField));
|
||
}
|
||
}
|
||
|
||
// 为移动原因输入框添加监听(带行索引验证)
|
||
for (int i = 0; i < movementReasons.Length; i++)
|
||
{
|
||
int rowIndex = i;
|
||
var inputField = movementReasons[i];
|
||
if (inputField == null) continue;
|
||
inputField.onValueChanged.AddListener((value) =>
|
||
{
|
||
OnMovementReasonChanged(value);
|
||
ValidateField(movementReasons, movementReasonAnswers, rowIndex, "移动原因");
|
||
});
|
||
}
|
||
|
||
// 为数量输入框添加监听(带行索引验证)
|
||
for (int i = 0; i < quantities.Length; i++)
|
||
{
|
||
int rowIndex = i;
|
||
var inputField = quantities[i];
|
||
if (inputField == null) continue;
|
||
inputField.onValueChanged.AddListener((value) =>
|
||
{
|
||
OnQuantityChanged(value);
|
||
ValidateField(quantities, quantityAnswers, rowIndex, "数量");
|
||
});
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// 按行校验:判断输入是否正确,只判断不清空,并打印验证结果
|
||
/// </summary>
|
||
private void ValidateField(TMP_InputField[] fields, string[] answers, int rowIndex, string label)
|
||
{
|
||
if (fields == null || answers == null) return;
|
||
if (rowIndex < 0 || rowIndex >= fields.Length) return;
|
||
var field = fields[rowIndex];
|
||
if (field == null) return;
|
||
|
||
// 检查该字段是否已完成验证,如果已完成则不再跟踪
|
||
var fieldKey = (rowIndex, label);
|
||
if (completedFields.Contains(fieldKey))
|
||
{
|
||
return; // 已完成验证,不再跟踪该字段的变化
|
||
}
|
||
|
||
string value = field.text == null ? string.Empty : field.text.Trim();
|
||
if (string.IsNullOrEmpty(value))
|
||
{
|
||
// 输入为空时,重置该字段的验证状态(但不移除已完成标记,因为可能用户误删)
|
||
var stateKey = (rowIndex, label);
|
||
if (fieldValidationStates.ContainsKey(stateKey))
|
||
{
|
||
fieldValidationStates[stateKey] = false;
|
||
}
|
||
return;
|
||
}
|
||
|
||
// 获取当前字段的验证状态
|
||
var validationKey = (rowIndex, label);
|
||
bool wasValidated = fieldValidationStates.ContainsKey(validationKey) && fieldValidationStates[validationKey];
|
||
|
||
// 未绑定行:
|
||
if (!rowToAnswerIndex.ContainsKey(rowIndex))
|
||
{
|
||
int bindIndex = FindUniqueIndex(answers, value);
|
||
|
||
if (bindIndex >= 0)
|
||
{
|
||
// 检查该答案组是否已被其他行使用
|
||
if (IsAnswerIndexUsed(bindIndex, rowIndex))
|
||
{
|
||
// 答案组已被使用,只判断不清空
|
||
//ShowInputOrderError($"第{bindIndex + 1}组答案已被其他行使用,不能重复绑定");
|
||
Debug.Log("不对");
|
||
// 重置验证状态
|
||
fieldValidationStates[validationKey] = false;
|
||
return;
|
||
}
|
||
|
||
// 可以唯一确定答案组,进行绑定
|
||
AssignRowAnswerIndex(rowIndex, bindIndex);
|
||
Debug.Log("对");
|
||
// 只有当之前未验证通过时,才触发向导(避免重复触发)
|
||
if (!wasValidated)
|
||
{
|
||
TutorialGuideManager.Instance.TriggerNextGuide();
|
||
fieldValidationStates[validationKey] = true;
|
||
// 标记该字段为已完成验证,后续不再跟踪
|
||
completedFields.Add(validationKey);
|
||
}
|
||
// 验证该行其他字段
|
||
CheckOtherFieldsConsistency(rowIndex);
|
||
return;
|
||
}
|
||
|
||
// 无法唯一确定(例如 HMA1/01M0/3 等重复值):
|
||
// 检查是否存在于答案集合中
|
||
if (ExistsInAnswers(answers, value))
|
||
{
|
||
// 值存在于答案集合中,但无法确定是哪个组,暂时允许(等待绑定)
|
||
Debug.Log("对");
|
||
// 只有当之前未验证通过时,才触发向导(避免重复触发)
|
||
if (!wasValidated)
|
||
{
|
||
TutorialGuideManager.Instance.TriggerNextGuide();
|
||
fieldValidationStates[validationKey] = true;
|
||
// 标记该字段为已完成验证,后续不再跟踪
|
||
completedFields.Add(validationKey);
|
||
}
|
||
}
|
||
else
|
||
{
|
||
// 该值在该字段的答案集合中完全不存在
|
||
//ShowInputOrderError($"第{rowIndex + 1}行{label}输入不在允许范围内");
|
||
Debug.Log("不对");
|
||
// 重置验证状态
|
||
fieldValidationStates[validationKey] = false;
|
||
}
|
||
|
||
return;
|
||
}
|
||
|
||
// 已绑定行:所有字段必须匹配绑定的答案组
|
||
int expectedIndex = rowToAnswerIndex[rowIndex];
|
||
if (expectedIndex < 0 || expectedIndex >= answers.Length) return;
|
||
|
||
string expected = answers[expectedIndex];
|
||
if (string.Equals(value, expected, StringComparison.OrdinalIgnoreCase))
|
||
{
|
||
// 输入正确
|
||
Debug.Log("对");
|
||
// 只有当之前未验证通过时,才触发向导(避免重复触发)
|
||
if (!wasValidated)
|
||
{
|
||
TutorialGuideManager.Instance.TriggerNextGuide();
|
||
fieldValidationStates[validationKey] = true;
|
||
// 标记该字段为已完成验证,后续不再跟踪
|
||
completedFields.Add(validationKey);
|
||
}
|
||
}
|
||
else
|
||
{
|
||
// 输入错误,只判断不清空
|
||
//ShowInputOrderError($"第{rowIndex + 1}行已绑定到第{expectedIndex + 1}组,{label}应为:{expected}");
|
||
Debug.Log("不对");
|
||
// 重置验证状态(当输入变为不正确时,下次再次输入正确时才会触发向导)
|
||
fieldValidationStates[validationKey] = false;
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// 在某字段答案数组中查找值的唯一索引(仅当且仅当出现一次时返回索引,否则返回-1)
|
||
/// </summary>
|
||
private int FindUniqueIndex(string[] answers, string value)
|
||
{
|
||
if (answers == null || answers.Length == 0) return -1;
|
||
if (string.IsNullOrEmpty(value)) return -1;
|
||
|
||
int found = -1;
|
||
for (int i = 0; i < answers.Length; i++)
|
||
{
|
||
// 跳过空字符串(表示该索引位置没有答案配置)
|
||
if (string.IsNullOrEmpty(answers[i])) continue;
|
||
|
||
if (string.Equals(answers[i], value, StringComparison.OrdinalIgnoreCase))
|
||
{
|
||
if (found != -1) return -1; // 出现两次及以上:不唯一
|
||
found = i;
|
||
}
|
||
}
|
||
|
||
return found;
|
||
}
|
||
|
||
/// <summary>
|
||
/// 值是否存在于该字段的答案集合中
|
||
/// </summary>
|
||
private bool ExistsInAnswers(string[] answers, string value)
|
||
{
|
||
if (answers == null || answers.Length == 0) return false;
|
||
if (string.IsNullOrEmpty(value)) return false;
|
||
|
||
for (int i = 0; i < answers.Length; i++)
|
||
{
|
||
// 跳过空字符串(表示该索引位置没有答案配置)
|
||
if (string.IsNullOrEmpty(answers[i])) continue;
|
||
|
||
if (string.Equals(answers[i], value, StringComparison.OrdinalIgnoreCase)) return true;
|
||
}
|
||
|
||
return false;
|
||
}
|
||
|
||
/// <summary>
|
||
/// 检查答案组索引是否已被其他行使用
|
||
/// </summary>
|
||
/// <param name="answerIndex">答案组索引</param>
|
||
/// <param name="excludeRowIndex">排除的行索引(当前正在处理的行)</param>
|
||
/// <returns>是否已被使用</returns>
|
||
private bool IsAnswerIndexUsed(int answerIndex, int excludeRowIndex)
|
||
{
|
||
foreach (var kvp in rowToAnswerIndex)
|
||
{
|
||
// 如果其他行已经绑定了该答案组,则返回true
|
||
if (kvp.Key != excludeRowIndex && kvp.Value == answerIndex)
|
||
{
|
||
return true;
|
||
}
|
||
}
|
||
|
||
return false;
|
||
}
|
||
|
||
/// <summary>
|
||
/// 绑定某一行对应的答案组
|
||
/// </summary>
|
||
private void AssignRowAnswerIndex(int rowIndex, int answerIndex)
|
||
{
|
||
rowToAnswerIndex[rowIndex] = answerIndex;
|
||
Debug.Log($"无序绑定:第{rowIndex + 1}行绑定到第{answerIndex + 1}组");
|
||
}
|
||
|
||
/// <summary>
|
||
/// 检查已绑定行的其他字段一致性:只判断不清空
|
||
/// </summary>
|
||
private void CheckOtherFieldsConsistency(int rowIndex)
|
||
{
|
||
if (!rowToAnswerIndex.ContainsKey(rowIndex)) return;
|
||
int idx = rowToAnswerIndex[rowIndex];
|
||
|
||
void check(TMP_InputField[] fields, string[] answers, string label)
|
||
{
|
||
if (fields == null || answers == null) return;
|
||
if (rowIndex < 0 || rowIndex >= fields.Length) return;
|
||
if (idx < 0 || idx >= answers.Length) return;
|
||
var f = fields[rowIndex];
|
||
if (f == null) return;
|
||
string v = f.text == null ? string.Empty : f.text.Trim();
|
||
if (string.IsNullOrEmpty(v)) return;
|
||
string expected = answers[idx];
|
||
if (string.Equals(v, expected, StringComparison.OrdinalIgnoreCase))
|
||
{
|
||
// 输入正确
|
||
Debug.Log("对");
|
||
}
|
||
else
|
||
{
|
||
// 输入错误,只判断不清空
|
||
// ShowInputOrderError($"第{rowIndex + 1}行已绑定到第{idx + 1}组,{label}应为:{expected}");
|
||
Debug.Log("不对");
|
||
}
|
||
}
|
||
|
||
check(materialCodes, materialCodeAnswers, "物料编码");
|
||
check(storageLocations, storageLocationAnswers, "库存地点");
|
||
check(factories, factoryAnswers, "工厂");
|
||
check(batchs, batchAnswers, "批次");
|
||
check(movementReasons, movementReasonAnswers, "移动原因");
|
||
check(quantities, quantityAnswers, "数量");
|
||
}
|
||
|
||
/// <summary>
|
||
/// 更新输入框状态,根据前置条件启用/禁用输入框
|
||
/// </summary>
|
||
private void UpdateInputFieldStates()
|
||
{
|
||
// 物料编码输入框始终可用
|
||
SetInputFieldsInteractable(materialCodes, true);
|
||
|
||
// 库存地点输入框:允许用户开始输入流程,不要求物料编码完全完成
|
||
SetInputFieldsInteractable(storageLocations, true);
|
||
|
||
// 工厂输入框:允许用户开始输入流程,不要求库存地点完全完成
|
||
SetInputFieldsInteractable(factories, true);
|
||
|
||
// 批次输入框:在教学模式下,只有在物料编码、库存地点、工厂都完成后才可用
|
||
bool canInputBatch = true; // 默认允许输入
|
||
if (IsTeachingMode)
|
||
{
|
||
canInputBatch = isMaterialCodeCompleted && isStorageLocationCompleted && isFactoryCompleted;
|
||
}
|
||
|
||
// 调试日志:检查批次输入框数组状态
|
||
Debug.Log($"批次输入框控制 - 教学模式: {IsTeachingMode}, 可输入: {canInputBatch}, 批次输入框数量: {batchs?.Length ?? 0}");
|
||
|
||
SetInputFieldsInteractable(batchs, canInputBatch, true); // 批次输入框需要特殊处理
|
||
|
||
// 移动原因输入框:始终可用
|
||
SetInputFieldsInteractable(movementReasons, true);
|
||
|
||
// 数量输入框:始终可用
|
||
SetInputFieldsInteractable(quantities, true);
|
||
}
|
||
|
||
/// <summary>
|
||
/// 设置输入框数组的交互状态
|
||
/// </summary>
|
||
/// <param name="inputFields">输入框数组</param>
|
||
/// <param name="interactable">是否可交互</param>
|
||
/// <param name="isBatchField">是否为批次输入框(需要特殊处理)</param>
|
||
private void SetInputFieldsInteractable(TMP_InputField[] inputFields, bool interactable, bool isBatchField = false)
|
||
{
|
||
if (inputFields == null)
|
||
{
|
||
Debug.LogWarning("输入框数组为null");
|
||
return;
|
||
}
|
||
|
||
int processedCount = 0;
|
||
|
||
if (!onlyFirst)
|
||
{
|
||
foreach (var inputField in inputFields)
|
||
{
|
||
if (inputField != null)
|
||
{
|
||
inputField.interactable = interactable;
|
||
processedCount++;
|
||
|
||
// 在教学模式下,对批次输入框进行特殊处理
|
||
if (IsTeachingMode && isBatchField)
|
||
{
|
||
// 使用readOnly属性完全阻止输入
|
||
inputField.readOnly = !interactable;
|
||
}
|
||
else if (isBatchField)
|
||
{
|
||
// 非教学模式下,批次输入框正常可用
|
||
inputField.readOnly = false;
|
||
}
|
||
|
||
// 添加视觉反馈:禁用时变灰
|
||
var colors = inputField.colors;
|
||
// colors.normalColor = interactable ? Color.white : Color.gray;
|
||
inputField.colors = colors;
|
||
}
|
||
}
|
||
}
|
||
else
|
||
{
|
||
TMP_InputField inputField = inputFields[0];
|
||
|
||
if (inputField != null)
|
||
{
|
||
inputField.interactable = interactable;
|
||
processedCount++;
|
||
|
||
// 在教学模式下,对批次输入框进行特殊处理
|
||
if (IsTeachingMode && isBatchField)
|
||
{
|
||
// 使用readOnly属性完全阻止输入
|
||
inputField.readOnly = !interactable;
|
||
}
|
||
else if (isBatchField)
|
||
{
|
||
// 非教学模式下,批次输入框正常可用
|
||
inputField.readOnly = false;
|
||
}
|
||
|
||
// 添加视觉反馈:禁用时变灰
|
||
var colors = inputField.colors;
|
||
// colors.normalColor = interactable ? Color.white : Color.gray;
|
||
inputField.colors = colors;
|
||
}
|
||
}
|
||
|
||
// 调试日志:显示处理的输入框数量
|
||
if (isBatchField)
|
||
{
|
||
Debug.Log($"批次输入框处理完成 - 总数: {inputFields.Length}, 已处理: {processedCount}, 可交互: {interactable}");
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// 检查输入框数组中是否有任何输入框被填写
|
||
/// </summary>
|
||
/// <param name="inputFields">输入框数组</param>
|
||
/// <returns>是否有输入框被填写</returns>
|
||
private bool IsAnyInputFieldFilled(TMP_InputField[] inputFields)
|
||
{
|
||
foreach (var inputField in inputFields)
|
||
{
|
||
if (inputField != null && !string.IsNullOrEmpty(inputField.text.Trim()))
|
||
{
|
||
return true;
|
||
}
|
||
}
|
||
|
||
return false;
|
||
}
|
||
|
||
/// <summary>
|
||
/// 智能检查输入框是否完成(根据onlyFirst决定检查范围)
|
||
/// </summary>
|
||
/// <param name="inputFields">输入框数组</param>
|
||
/// <returns>输入框是否完成</returns>
|
||
private bool IsInputFieldCompleted(TMP_InputField[] inputFields)
|
||
{
|
||
if (inputFields == null || inputFields.Length == 0)
|
||
{
|
||
return false;
|
||
}
|
||
|
||
if (onlyFirst)
|
||
{
|
||
// 只检查第一个输入框
|
||
return inputFields[0] != null && !string.IsNullOrEmpty(inputFields[0].text.Trim());
|
||
}
|
||
else
|
||
{
|
||
// 检查所有输入框
|
||
return IsAnyInputFieldFilled(inputFields);
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// 物料编码输入变化事件处理
|
||
/// </summary>
|
||
/// <param name="value">输入值</param>
|
||
private void OnMaterialCodeChanged(string value)
|
||
{
|
||
// 检查物料编码是否完成(根据onlyFirst决定检查范围)
|
||
isMaterialCodeCompleted = IsInputFieldCompleted(materialCodes);
|
||
|
||
// 更新输入框状态
|
||
UpdateInputFieldStates();
|
||
|
||
Debug.Log($"物料编码状态更新: {isMaterialCodeCompleted} (onlyFirst: {onlyFirst})");
|
||
}
|
||
|
||
/// <summary>
|
||
/// 库存地点输入变化事件处理
|
||
/// </summary>
|
||
/// <param name="value">输入值</param>
|
||
private void OnStorageLocationChanged(string value)
|
||
{
|
||
// 检查库存地点是否完成(根据onlyFirst决定检查范围)
|
||
isStorageLocationCompleted = IsInputFieldCompleted(storageLocations);
|
||
|
||
// 更新输入框状态
|
||
UpdateInputFieldStates();
|
||
|
||
Debug.Log($"库存地点状态更新: {isStorageLocationCompleted} (onlyFirst: {onlyFirst})");
|
||
}
|
||
|
||
/// <summary>
|
||
/// 工厂输入变化事件处理
|
||
/// </summary>
|
||
/// <param name="value">输入值</param>
|
||
private void OnFactoryChanged(string value)
|
||
{
|
||
// 检查工厂是否完成(根据onlyFirst决定检查范围)
|
||
isFactoryCompleted = IsInputFieldCompleted(factories);
|
||
|
||
// 更新输入框状态
|
||
UpdateInputFieldStates();
|
||
|
||
Debug.Log($"工厂状态更新: {isFactoryCompleted} (onlyFirst: {onlyFirst})");
|
||
}
|
||
|
||
/// <summary>
|
||
/// 批次输入变化事件处理
|
||
/// </summary>
|
||
/// <param name="value">输入值</param>
|
||
private void OnBatchChanged(string value)
|
||
{
|
||
// 验证输入顺序:只有在物料编码、库存地点、工厂都完成后才能输入批次
|
||
if (!string.IsNullOrEmpty(value.Trim()) && !(isMaterialCodeCompleted && isStorageLocationCompleted && isFactoryCompleted))
|
||
{
|
||
// 输入顺序错误,清空批次输入并提示
|
||
foreach (var batch in batchs)
|
||
{
|
||
if (batch.text == value)
|
||
{
|
||
batch.text = "";
|
||
break;
|
||
}
|
||
}
|
||
|
||
// 显示错误提示
|
||
//ShowInputOrderError("请先完成物料编码、库存地点、工厂的输入,再输入批次号");
|
||
isInputOrderValid = false;
|
||
return;
|
||
}
|
||
|
||
isInputOrderValid = true;
|
||
|
||
// 更新输入框状态
|
||
UpdateInputFieldStates();
|
||
|
||
Debug.Log($"批次输入验证: 顺序有效 = {isInputOrderValid}");
|
||
}
|
||
|
||
/// <summary>
|
||
/// 批次输入框获得焦点事件处理(教学模式专用)
|
||
/// </summary>
|
||
/// <param name="inputField">获得焦点的输入框</param>
|
||
private void OnBatchFieldSelected(TMP_InputField inputField)
|
||
{
|
||
// 检查前置条件是否满足
|
||
if (!(isMaterialCodeCompleted && isStorageLocationCompleted && isFactoryCompleted))
|
||
{
|
||
// 前置条件不满足,立即取消焦点
|
||
inputField.DeactivateInputField();
|
||
|
||
// 显示提示信息
|
||
//ShowInputOrderError("请先完成物料编码、库存地点、工厂的输入,再输入批次号");
|
||
|
||
Debug.Log("教学模式:批次输入框焦点被阻止,前置条件未满足");
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// 移动原因输入变化事件处理
|
||
/// </summary>
|
||
/// <param name="value">输入值</param>
|
||
private void OnMovementReasonChanged(string value)
|
||
{
|
||
// 更新输入框状态
|
||
UpdateInputFieldStates();
|
||
}
|
||
|
||
/// <summary>
|
||
/// 数量输入变化事件处理
|
||
/// </summary>
|
||
/// <param name="value">输入值</param>
|
||
private void OnQuantityChanged(string value)
|
||
{
|
||
// 更新输入框状态
|
||
UpdateInputFieldStates();
|
||
}
|
||
|
||
// /// <summary>
|
||
// /// 显示输入顺序错误提示
|
||
// /// </summary>
|
||
// /// <param name="message">错误消息</param>
|
||
// private void ShowInputOrderError(string message)
|
||
// {
|
||
// // 使用现有的AutoHideScript显示错误提示
|
||
// if (autoHideScript != null)
|
||
// {
|
||
// autoHideScript.ShowObject(message);
|
||
// }
|
||
//
|
||
// Debug.LogWarning($"输入顺序错误: {message}");
|
||
// }
|
||
|
||
/// <summary>
|
||
/// 提交前整体校验:若某行任一字段填写,则该字段必须等于该行绑定的标准答案
|
||
/// </summary>
|
||
private bool ValidateAllRows()
|
||
{
|
||
int rowCount = Math.Max(0, Math.Max(
|
||
Math.Max(materialCodes?.Length ?? 0, storageLocations?.Length ?? 0),
|
||
Math.Max(factories?.Length ?? 0, Math.Max(batchs?.Length ?? 0, Math.Max(movementReasons?.Length ?? 0, quantities?.Length ?? 0)))));
|
||
|
||
for (int i = 0; i < rowCount; i++)
|
||
{
|
||
// 获取该行绑定的答案组索引(如果已绑定)
|
||
int answerIndex = -1;
|
||
if (rowToAnswerIndex.ContainsKey(i))
|
||
{
|
||
answerIndex = rowToAnswerIndex[i];
|
||
}
|
||
else
|
||
{
|
||
// 未绑定的行:尝试通过输入值找到唯一对应的答案组
|
||
// 首先尝试通过物料编码查找(通常是最唯一的值)
|
||
if (materialCodes != null && i < materialCodes.Length && materialCodes[i] != null)
|
||
{
|
||
string v = materialCodes[i].text?.Trim() ?? string.Empty;
|
||
if (!string.IsNullOrEmpty(v))
|
||
{
|
||
answerIndex = FindUniqueIndex(materialCodeAnswers, v);
|
||
}
|
||
}
|
||
|
||
// 如果物料编码无法唯一确定,尝试其他字段
|
||
if (answerIndex < 0 && storageLocations != null && i < storageLocations.Length && storageLocations[i] != null)
|
||
{
|
||
string v = storageLocations[i].text?.Trim() ?? string.Empty;
|
||
if (!string.IsNullOrEmpty(v))
|
||
{
|
||
answerIndex = FindUniqueIndex(storageLocationAnswers, v);
|
||
}
|
||
}
|
||
|
||
// 如果仍未找到,且没有填写任何字段,跳过该行
|
||
if (answerIndex < 0)
|
||
{
|
||
// 检查该行是否有任何输入
|
||
bool hasAnyInput = false;
|
||
if (materialCodes != null && i < materialCodes.Length && materialCodes[i] != null && !string.IsNullOrEmpty(materialCodes[i].text?.Trim()))
|
||
hasAnyInput = true;
|
||
if (!hasAnyInput && storageLocations != null && i < storageLocations.Length && storageLocations[i] != null && !string.IsNullOrEmpty(storageLocations[i].text?.Trim()))
|
||
hasAnyInput = true;
|
||
if (!hasAnyInput && factories != null && i < factories.Length && factories[i] != null && !string.IsNullOrEmpty(factories[i].text?.Trim()))
|
||
hasAnyInput = true;
|
||
if (!hasAnyInput && batchs != null && i < batchs.Length && batchs[i] != null && !string.IsNullOrEmpty(batchs[i].text?.Trim()))
|
||
hasAnyInput = true;
|
||
if (!hasAnyInput && movementReasons != null && i < movementReasons.Length && movementReasons[i] != null && !string.IsNullOrEmpty(movementReasons[i].text?.Trim()))
|
||
hasAnyInput = true;
|
||
if (!hasAnyInput && quantities != null && i < quantities.Length && quantities[i] != null && !string.IsNullOrEmpty(quantities[i].text?.Trim()))
|
||
hasAnyInput = true;
|
||
|
||
// 如果该行有输入但无法绑定到答案组,说明输入错误
|
||
if (hasAnyInput)
|
||
{
|
||
Debug.LogWarning($"第{i + 1}行有输入但无法唯一确定对应的答案组");
|
||
return false;
|
||
}
|
||
|
||
// 如果该行没有任何输入,跳过验证
|
||
continue;
|
||
}
|
||
}
|
||
|
||
// 使用绑定的答案组索引验证该行的所有字段(如果answerIndex无效则跳过)
|
||
if (answerIndex < 0) continue;
|
||
|
||
// 验证物料编码
|
||
if (materialCodes != null && i < materialCodes.Length && materialCodes[i] != null)
|
||
{
|
||
string v = materialCodes[i].text?.Trim() ?? string.Empty;
|
||
if (!string.IsNullOrEmpty(v))
|
||
{
|
||
if (answerIndex >= materialCodeAnswers.Length || !string.Equals(v, materialCodeAnswers[answerIndex], StringComparison.OrdinalIgnoreCase))
|
||
{
|
||
Debug.LogWarning($"第{i + 1}行物料编码应为:{materialCodeAnswers[answerIndex]},实际输入:{v}");
|
||
return false;
|
||
}
|
||
}
|
||
}
|
||
|
||
// 验证库存地点
|
||
if (storageLocations != null && i < storageLocations.Length && storageLocations[i] != null)
|
||
{
|
||
string v = storageLocations[i].text?.Trim() ?? string.Empty;
|
||
if (!string.IsNullOrEmpty(v))
|
||
{
|
||
if (answerIndex >= storageLocationAnswers.Length || !string.Equals(v, storageLocationAnswers[answerIndex], StringComparison.OrdinalIgnoreCase))
|
||
{
|
||
Debug.LogWarning($"第{i + 1}行库存地点应为:{storageLocationAnswers[answerIndex]},实际输入:{v}");
|
||
return false;
|
||
}
|
||
}
|
||
}
|
||
|
||
// 验证工厂
|
||
if (factories != null && i < factories.Length && factories[i] != null)
|
||
{
|
||
string v = factories[i].text?.Trim() ?? string.Empty;
|
||
if (!string.IsNullOrEmpty(v))
|
||
{
|
||
if (answerIndex >= factoryAnswers.Length || !string.Equals(v, factoryAnswers[answerIndex], StringComparison.OrdinalIgnoreCase))
|
||
{
|
||
Debug.LogWarning($"第{i + 1}行工厂应为:{factoryAnswers[answerIndex]},实际输入:{v}");
|
||
return false;
|
||
}
|
||
}
|
||
}
|
||
|
||
// 验证批次
|
||
if (batchs != null && i < batchs.Length && batchs[i] != null)
|
||
{
|
||
string v = batchs[i].text?.Trim() ?? string.Empty;
|
||
if (!string.IsNullOrEmpty(v))
|
||
{
|
||
if (answerIndex >= batchAnswers.Length || !string.Equals(v, batchAnswers[answerIndex], StringComparison.OrdinalIgnoreCase))
|
||
{
|
||
Debug.LogWarning($"第{i + 1}行批次应为:{batchAnswers[answerIndex]},实际输入:{v}");
|
||
return false;
|
||
}
|
||
}
|
||
}
|
||
|
||
// 验证移动原因
|
||
if (movementReasons != null && i < movementReasons.Length && movementReasons[i] != null)
|
||
{
|
||
string v = movementReasons[i].text?.Trim() ?? string.Empty;
|
||
if (!string.IsNullOrEmpty(v))
|
||
{
|
||
if (answerIndex >= movementReasonAnswers.Length || !string.Equals(v, movementReasonAnswers[answerIndex], StringComparison.OrdinalIgnoreCase))
|
||
{
|
||
Debug.LogWarning($"第{i + 1}行移动原因应为:{movementReasonAnswers[answerIndex]},实际输入:{v}");
|
||
return false;
|
||
}
|
||
}
|
||
}
|
||
|
||
// 验证数量
|
||
if (quantities != null && i < quantities.Length && quantities[i] != null)
|
||
{
|
||
string v = quantities[i].text?.Trim() ?? string.Empty;
|
||
if (!string.IsNullOrEmpty(v))
|
||
{
|
||
if (answerIndex >= quantityAnswers.Length || !string.Equals(v, quantityAnswers[answerIndex], StringComparison.OrdinalIgnoreCase))
|
||
{
|
||
Debug.LogWarning($"第{i + 1}行数量应为:{quantityAnswers[answerIndex]},实际输入:{v}");
|
||
return false;
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
return true;
|
||
}
|
||
|
||
/// <summary>
|
||
/// 验证输入顺序是否有效
|
||
/// </summary>
|
||
/// <returns>输入顺序是否有效</returns>
|
||
private bool ValidateInputOrder()
|
||
{
|
||
// 检查是否所有必需的字段都按顺序完成
|
||
bool materialCodeValid = isMaterialCodeCompleted;
|
||
bool storageLocationValid = isStorageLocationCompleted && materialCodeValid;
|
||
bool factoryValid = isFactoryCompleted && storageLocationValid;
|
||
bool batchValid = IsAnyInputFieldFilled(batchs) && factoryValid;
|
||
bool movementReasonValid = IsAnyInputFieldFilled(movementReasons) && batchValid;
|
||
bool quantityValid = IsAnyInputFieldFilled(quantities) && movementReasonValid;
|
||
|
||
return materialCodeValid && storageLocationValid && factoryValid && batchValid && movementReasonValid && quantityValid;
|
||
}
|
||
|
||
/// <summary>
|
||
/// 从答案数组构建 parameters(验证成功时使用)
|
||
/// </summary>
|
||
/// <param name="parameters">参数列表(已包含两个下拉框的值)</param>
|
||
private void BuildParametersFromAnswers(List<string> parameters)
|
||
{
|
||
if (onlyFirst)
|
||
{
|
||
// 只添加每个答案数组的第一个答案
|
||
if (materialCodeAnswers.Length > 0) parameters.Add(materialCodeAnswers[0]);
|
||
if (storageLocationAnswers.Length > 0) parameters.Add(storageLocationAnswers[0]);
|
||
if (factoryAnswers.Length > 0) parameters.Add(factoryAnswers[0]);
|
||
if (movementReasonAnswers.Length > 0) parameters.Add(movementReasonAnswers[0]);
|
||
if (quantityAnswers.Length > 0) parameters.Add(quantityAnswers[0]);
|
||
if (batchAnswers.Length > 0) parameters.Add(batchAnswers[0]);
|
||
}
|
||
else
|
||
{
|
||
// 添加所有答案:按字段类型分组,每种类型的所有答案连续添加
|
||
// 物料编码答案
|
||
foreach (var answer in materialCodeAnswers)
|
||
{
|
||
parameters.Add(answer);
|
||
}
|
||
|
||
// 库存地点答案
|
||
foreach (var answer in storageLocationAnswers)
|
||
{
|
||
parameters.Add(answer);
|
||
}
|
||
|
||
// 工厂答案
|
||
foreach (var answer in factoryAnswers)
|
||
{
|
||
parameters.Add(answer);
|
||
}
|
||
|
||
// 移动原因答案
|
||
foreach (var answer in movementReasonAnswers)
|
||
{
|
||
parameters.Add(answer);
|
||
}
|
||
|
||
// 数量答案
|
||
foreach (var answer in quantityAnswers)
|
||
{
|
||
parameters.Add(answer);
|
||
}
|
||
|
||
// 批次答案
|
||
foreach (var answer in batchAnswers)
|
||
{
|
||
parameters.Add(answer);
|
||
}
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// 从输入框构建 parameters(验证失败或默认使用)
|
||
/// </summary>
|
||
/// <param name="parameters">参数列表(已包含两个下拉框的值)</param>
|
||
private void BuildParametersFromInputs(List<string> parameters)
|
||
{
|
||
if (onlyFirst)
|
||
{
|
||
// 只添加每个数组的第一个输入框的值
|
||
if (materialCodes.Length > 0) parameters.Add(materialCodes[0].text);
|
||
if (storageLocations.Length > 0) parameters.Add(storageLocations[0].text);
|
||
if (factories.Length > 0) parameters.Add(factories[0].text);
|
||
if (movementReasons.Length > 0) parameters.Add(movementReasons[0].text);
|
||
if (quantities.Length > 0) parameters.Add(quantities[0].text);
|
||
if (batchs.Length > 0) parameters.Add(batchs[0].text);
|
||
}
|
||
else
|
||
{
|
||
foreach (var code in materialCodes)
|
||
{
|
||
parameters.Add(code.text);
|
||
}
|
||
|
||
foreach (var location in storageLocations)
|
||
{
|
||
parameters.Add(location.text);
|
||
}
|
||
|
||
foreach (var factory in factories)
|
||
{
|
||
parameters.Add(factory.text);
|
||
}
|
||
|
||
foreach (var reason in movementReasons)
|
||
{
|
||
parameters.Add(reason.text);
|
||
}
|
||
foreach (var quantity in quantities)
|
||
{
|
||
parameters.Add(quantity.text);
|
||
}
|
||
// 添加所有输入框的值
|
||
foreach (var batch in batchs)
|
||
{
|
||
parameters.Add(batch.text);
|
||
}
|
||
}
|
||
}
|
||
|
||
private void OnQueryButtonClicked()
|
||
{
|
||
// 所有模式都执行验证,验证成功则使用答案,验证失败则使用输入
|
||
bool validationPassed = false;
|
||
|
||
// 首先验证输入顺序
|
||
if (ValidateInputOrder())
|
||
{
|
||
// 输入顺序验证通过,再进行整体验证
|
||
if (ValidateAllRows())
|
||
{
|
||
// 验证完全通过,使用答案填充
|
||
validationPassed = true;
|
||
}
|
||
}
|
||
|
||
List<string> parameters = new List<string>();
|
||
// 添加两个下拉框的选中值
|
||
parameters.Add(quantitiesDropdown.options[quantitiesDropdown.value].text);
|
||
parameters.Add(quantitiesDropdown2.options[quantitiesDropdown2.value].text);
|
||
|
||
// 根据验证结果决定使用答案还是用户输入
|
||
if (validationPassed)
|
||
{
|
||
// 验证成功,使用动作的答案填充
|
||
BuildParametersFromAnswers(parameters);
|
||
}
|
||
else
|
||
{
|
||
// 验证失败,使用输入框的内容填充
|
||
BuildParametersFromInputs(parameters);
|
||
}
|
||
|
||
if (MotionEngine.GetModule<ProcessManager>().HandleClick(parameters))
|
||
{
|
||
// 保存提交前的onlyFirst状态
|
||
bool wasOnlyFirst = onlyFirst;
|
||
|
||
onlyFirst = true;
|
||
Debug.Log("查询成功");
|
||
titleText.text = "物料凭证 500004650 已过账";
|
||
autoHideScript.ShowObject("已过账");
|
||
|
||
// 清空所有输入框的内容
|
||
foreach (var batch in batchs)
|
||
{
|
||
batch.text = "";
|
||
}
|
||
|
||
foreach (var code in materialCodes)
|
||
{
|
||
code.text = "";
|
||
}
|
||
|
||
foreach (var location in storageLocations)
|
||
{
|
||
location.text = "";
|
||
}
|
||
|
||
foreach (var factory in factories)
|
||
{
|
||
factory.text = "";
|
||
}
|
||
|
||
foreach (var reason in movementReasons)
|
||
{
|
||
reason.text = "";
|
||
}
|
||
|
||
foreach (var quantity in quantities)
|
||
{
|
||
quantity.text = "";
|
||
}
|
||
|
||
foreach (var VARIABLE in kucundidian)
|
||
{
|
||
VARIABLE.text = "";
|
||
}
|
||
|
||
foreach (var VARIABLE in picichuanshu)
|
||
{
|
||
VARIABLE.text = "";
|
||
}
|
||
|
||
// 如果不是只使用第一个(提交前onlyFirst为false时),清空绑定记录,以便下一个动作重新绑定
|
||
if (!wasOnlyFirst)
|
||
{
|
||
rowToAnswerIndex.Clear();
|
||
// 清空所有字段的验证状态和已完成标记
|
||
fieldValidationStates.Clear();
|
||
completedFields.Clear();
|
||
Debug.Log("清空绑定记录和验证状态,准备下一个动作的答案验证");
|
||
|
||
// 重新从框架获取新的动作答案(下一个动作可能不同)
|
||
LoadAnswersFromFramework();
|
||
}
|
||
else
|
||
{
|
||
// 即使是onlyFirst模式,也清空验证状态以便重新验证
|
||
fieldValidationStates.Clear();
|
||
completedFields.Clear();
|
||
}
|
||
|
||
InitializeDropdowns();
|
||
TutorialGuideManager.Instance.TriggerNextGuide(queryButton.name);
|
||
}
|
||
}
|
||
}
|
||
} |