first commit
This commit is contained in:
655
procedure/proceduremanager.cpp
Normal file
655
procedure/proceduremanager.cpp
Normal file
@@ -0,0 +1,655 @@
|
||||
#include "proceduremanager.h"
|
||||
#include "procedureparser.h"
|
||||
#include <QDir>
|
||||
#include <QFile>
|
||||
#include <QDebug>
|
||||
#include <QFileInfo>
|
||||
#include <QJsonDocument>
|
||||
#include <QJsonObject>
|
||||
#include <QJsonArray>
|
||||
#include <QCoreApplication>
|
||||
|
||||
ProcedureManager::ProcedureManager(QObject *parent)
|
||||
: QObject(parent)
|
||||
{
|
||||
// 不再自动创建示例数据,等待调用 loadProcedureList
|
||||
}
|
||||
|
||||
ProcedureManager::~ProcedureManager()
|
||||
{
|
||||
}
|
||||
|
||||
QVector<ProcedureSummary> ProcedureManager::loadProcedureList(const QString &directory)
|
||||
{
|
||||
m_procedureDirectory = directory;
|
||||
m_procedureList.clear();
|
||||
|
||||
QDir dir(directory);
|
||||
if (!dir.exists())
|
||||
{
|
||||
qWarning() << "Procedure directory does not exist:" << directory;
|
||||
createSampleProcedures();
|
||||
return m_procedureList;
|
||||
}
|
||||
|
||||
// 扫描目录中的 YAML 和 JSON 文件
|
||||
QStringList filters;
|
||||
filters << "*.yaml" << "*.yml" << "*.json";
|
||||
dir.setNameFilters(filters);
|
||||
|
||||
QFileInfoList files = dir.entryInfoList(QDir::Files | QDir::Readable);
|
||||
qDebug() << "Found" << files.size() << "procedure files in" << directory;
|
||||
|
||||
for (const QFileInfo &fileInfo : files)
|
||||
{
|
||||
QString filePath = fileInfo.absoluteFilePath();
|
||||
qDebug() << "Scanning procedure file:" << filePath;
|
||||
|
||||
// 使用 ProcedureParser 解析文件
|
||||
ProcedureParser parser;
|
||||
if (parser.loadConfig(filePath))
|
||||
{
|
||||
ProcedureConfig config = parser.parseProcedureConfig();
|
||||
|
||||
// 创建摘要信息
|
||||
ProcedureSummary summary;
|
||||
summary.id = config.procedureId;
|
||||
summary.name = config.procedureName;
|
||||
summary.version = config.version;
|
||||
summary.description = config.description;
|
||||
summary.filePath = filePath;
|
||||
|
||||
m_procedureList.append(summary);
|
||||
|
||||
qDebug() << "Loaded procedure:" << summary.name
|
||||
<< "ID:" << summary.id
|
||||
<< "Version:" << summary.version;
|
||||
}
|
||||
else
|
||||
{
|
||||
qWarning() << "Failed to parse procedure file:" << filePath;
|
||||
}
|
||||
}
|
||||
|
||||
// 如果没有找到任何文件,创建示例数据
|
||||
if (m_procedureList.isEmpty())
|
||||
{
|
||||
qDebug() << "No valid procedure files found, creating sample data";
|
||||
createSampleProcedures();
|
||||
}
|
||||
else
|
||||
{
|
||||
// 即使找到了真实文件,也添加mock异常数据用于测试
|
||||
qDebug() << "Adding mock exception data for testing";
|
||||
createMockExceptionData();
|
||||
}
|
||||
|
||||
return m_procedureList;
|
||||
}
|
||||
|
||||
QVector<ProcedureSummary> ProcedureManager::searchProcedures(const QString &keyword)
|
||||
{
|
||||
if (keyword.isEmpty())
|
||||
{
|
||||
return m_procedureList;
|
||||
}
|
||||
|
||||
QVector<ProcedureSummary> results;
|
||||
for (const auto &proc : m_procedureList)
|
||||
{
|
||||
if (proc.id.contains(keyword, Qt::CaseInsensitive) ||
|
||||
proc.name.contains(keyword, Qt::CaseInsensitive))
|
||||
{
|
||||
results.append(proc);
|
||||
}
|
||||
}
|
||||
return results;
|
||||
}
|
||||
|
||||
ProcedureData ProcedureManager::loadProcedure(const QString &procedureId)
|
||||
{
|
||||
if (m_loadedProcedures.contains(procedureId))
|
||||
{
|
||||
return m_loadedProcedures[procedureId];
|
||||
}
|
||||
|
||||
// 创建示例规程
|
||||
ProcedureData proc;
|
||||
proc.id = procedureId;
|
||||
proc.workOrderId = m_workOrderId;
|
||||
|
||||
if (procedureId == "KMCIXRCP503")
|
||||
{
|
||||
proc.name = "一回路温度传感器绝缘和连续性检查:TP RCP63";
|
||||
proc.version = "C4";
|
||||
proc.description = "本程序适用于热停堆(热功率稳定)工况下执行RCP63程序";
|
||||
|
||||
// 创建任务组
|
||||
TaskGroup group1;
|
||||
group1.id = "preInspection";
|
||||
group1.name = "5.1 试验前状态说明和检查";
|
||||
|
||||
// 添加步骤
|
||||
StepData step1;
|
||||
step1.id = "step_001";
|
||||
step1.type = StepType::Manual;
|
||||
step1.content = "本程序适用于热停堆(热功率稳定)工况下执行RCP63程序(K-MT-I-X-RCP-501)统一进行Sensor Check 部分使用。";
|
||||
step1.status = StepStatus::Confirmed;
|
||||
group1.steps.append(step1);
|
||||
|
||||
StepData step2;
|
||||
step2.id = "step_002";
|
||||
step2.type = StepType::Automatic;
|
||||
step2.content = "执行前确认KIC中一回路三个环路平均温度变化量不超过0.2℃;";
|
||||
step2.status = StepStatus::Passed;
|
||||
step2.tableRefs.append("temperatureCheckTable");
|
||||
step2.highlightFields.append("loop1Temp");
|
||||
step2.highlightFields.append("loop2Temp");
|
||||
step2.highlightFields.append("loop3Temp");
|
||||
group1.steps.append(step2);
|
||||
|
||||
StepData step3;
|
||||
step3.id = "step_003";
|
||||
step3.type = StepType::Automatic;
|
||||
step3.content = "若KIC中显示的一回路三个环路平均温度变化超过0.2℃,则采取滑动平均的计算方式记录滑动周期: (建议60s), 一环路平均温度滑动平均最大最小值之差;二环路平均温度滑动平均最大最小值之差;三环路平均温度滑动平均最大最小值之差;每个数据测量的最短时间(应大于滑动周期):。确认三个环路平均温度的滑动平均最大与最小值之差不超过0.2℃。";
|
||||
step3.status = StepStatus::Pending;
|
||||
group1.steps.append(step3);
|
||||
|
||||
StepData step4;
|
||||
step4.id = "step_004";
|
||||
step4.type = StepType::Manual;
|
||||
step4.content = "确认 RPR、RPN上无相关的试验检修工作。";
|
||||
step4.status = StepStatus::Pending;
|
||||
group1.steps.append(step4);
|
||||
|
||||
StepData step5;
|
||||
step5.id = "step_005";
|
||||
step5.type = StepType::Automatic;
|
||||
step5.content = "按附表1检查相关模拟量指示并记录,确认结果满意。";
|
||||
step5.status = StepStatus::Pending;
|
||||
step5.tableRefs.append("analogReadingsTable");
|
||||
group1.steps.append(step5);
|
||||
|
||||
StepData step6;
|
||||
step6.id = "step_006";
|
||||
step6.type = StepType::Automatic;
|
||||
step6.content = "试验前根据附表1报警清单检查报警,确认无异常报警,方可进行后续检查工作";
|
||||
step6.status = StepStatus::Pending;
|
||||
step6.tableRefs.append("alarmCheckTable");
|
||||
group1.steps.append(step6);
|
||||
|
||||
proc.taskGroups.append(group1);
|
||||
|
||||
// 创建表格
|
||||
TableData tempTable;
|
||||
tempTable.id = "temperatureCheckTable";
|
||||
tempTable.name = "环路平均温度变化";
|
||||
tempTable.description = "检验前后的环路温度数据";
|
||||
|
||||
TableField f1;
|
||||
f1.id = "loop1Temp";
|
||||
f1.name = "一环路平均温度";
|
||||
f1.type = "numeric";
|
||||
f1.unit = "℃";
|
||||
TableField f2;
|
||||
f2.id = "loop2Temp";
|
||||
f2.name = "二环路平均温度";
|
||||
f2.type = "numeric";
|
||||
f2.unit = "℃";
|
||||
TableField f3;
|
||||
f3.id = "loop3Temp";
|
||||
f3.name = "三环路平均温度";
|
||||
f3.type = "numeric";
|
||||
f3.unit = "℃";
|
||||
tempTable.columns.append(f1);
|
||||
tempTable.columns.append(f2);
|
||||
tempTable.columns.append(f3);
|
||||
proc.tables.append(tempTable);
|
||||
|
||||
TableData analogTable;
|
||||
analogTable.id = "analogReadingsTable";
|
||||
analogTable.name = "实验前后模拟量数据";
|
||||
proc.tables.append(analogTable);
|
||||
|
||||
TableData alarmTable;
|
||||
alarmTable.id = "alarmCheckTable";
|
||||
alarmTable.name = "试验前后报警检查";
|
||||
proc.tables.append(alarmTable);
|
||||
|
||||
// 计算步骤数
|
||||
proc.totalSteps = group1.steps.size();
|
||||
proc.completedSteps = 2; // 已完成2个步骤
|
||||
}
|
||||
else if (procedureId == "SIMPLE63")
|
||||
{
|
||||
proc.name = "范例 一回路温度传感器绝缘和连续性检查 TP RCP63";
|
||||
proc.version = "SIMPLE";
|
||||
proc.description = "范例规程";
|
||||
proc.totalSteps = 6;
|
||||
proc.completedSteps = 0;
|
||||
}
|
||||
else if (procedureId == "SIMPLE_TEST")
|
||||
{
|
||||
proc.name = "简单测试规程";
|
||||
proc.version = "1.0";
|
||||
proc.description = "这是一个简单的测试规程,用于演示 ProcedurePlayer 的基本功能。包含一个测试任务组和结果展示。";
|
||||
proc.totalSteps = 4;
|
||||
proc.completedSteps = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
// 尝试从 JSON 文件加载 mock 数据
|
||||
proc = loadMockProcedureFromJson(procedureId);
|
||||
|
||||
// 如果 JSON 中没有找到,返回空数据
|
||||
if (proc.name.isEmpty())
|
||||
{
|
||||
qWarning() << "Procedure not found:" << procedureId;
|
||||
}
|
||||
}
|
||||
|
||||
m_loadedProcedures[procedureId] = proc;
|
||||
emit procedureLoaded(proc);
|
||||
return proc;
|
||||
}
|
||||
|
||||
void ProcedureManager::setWorkOrderId(const QString &workOrderId)
|
||||
{
|
||||
m_workOrderId = workOrderId;
|
||||
}
|
||||
|
||||
bool ProcedureManager::confirmStep(const QString &procedureId, const QString &stepId)
|
||||
{
|
||||
if (!m_loadedProcedures.contains(procedureId))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
auto &proc = m_loadedProcedures[procedureId];
|
||||
for (auto &group : proc.taskGroups)
|
||||
{
|
||||
for (auto &step : group.steps)
|
||||
{
|
||||
if (step.id == stepId)
|
||||
{
|
||||
step.status = StepStatus::Confirmed;
|
||||
step.executedAt = QDateTime::currentDateTime();
|
||||
emit stepStatusChanged(stepId, StepStatus::Confirmed);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool ProcedureManager::cancelStepConfirm(const QString &procedureId, const QString &stepId, const QString &reason)
|
||||
{
|
||||
if (!m_loadedProcedures.contains(procedureId))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
auto &proc = m_loadedProcedures[procedureId];
|
||||
for (auto &group : proc.taskGroups)
|
||||
{
|
||||
for (auto &step : group.steps)
|
||||
{
|
||||
if (step.id == stepId)
|
||||
{
|
||||
step.status = StepStatus::Pending;
|
||||
step.cancelReason = reason;
|
||||
emit stepStatusChanged(stepId, StepStatus::Pending);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool ProcedureManager::executeAutoStep(const QString &procedureId, const QString &stepId)
|
||||
{
|
||||
// 模拟自动步骤执行
|
||||
if (!m_loadedProcedures.contains(procedureId))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
auto &proc = m_loadedProcedures[procedureId];
|
||||
for (auto &group : proc.taskGroups)
|
||||
{
|
||||
for (auto &step : group.steps)
|
||||
{
|
||||
if (step.id == stepId && step.type == StepType::Automatic)
|
||||
{
|
||||
step.status = StepStatus::InProgress;
|
||||
emit stepStatusChanged(stepId, StepStatus::InProgress);
|
||||
// 实际应用中这里会执行真正的自动化逻辑
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
TableData ProcedureManager::getTableData(const QString &procedureId, const QString &tableId)
|
||||
{
|
||||
if (m_loadedProcedures.contains(procedureId))
|
||||
{
|
||||
const auto &proc = m_loadedProcedures[procedureId];
|
||||
for (const auto &table : proc.tables)
|
||||
{
|
||||
if (table.id == tableId)
|
||||
{
|
||||
return table;
|
||||
}
|
||||
}
|
||||
}
|
||||
return TableData();
|
||||
}
|
||||
|
||||
bool ProcedureManager::updateTableData(const QString &procedureId, const QString &tableId, const QVector<QVariantMap> &rows)
|
||||
{
|
||||
if (!m_loadedProcedures.contains(procedureId))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
auto &proc = m_loadedProcedures[procedureId];
|
||||
for (auto &table : proc.tables)
|
||||
{
|
||||
if (table.id == tableId)
|
||||
{
|
||||
table.rows = rows;
|
||||
emit tableDataUpdated(tableId);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void ProcedureManager::createSampleProcedures()
|
||||
{
|
||||
m_procedureList.clear();
|
||||
|
||||
ProcedureSummary p1;
|
||||
p1.id = "KMCIXRCP503";
|
||||
p1.name = "一回路温度传感器绝缘和连续性检查:TP RCP63";
|
||||
p1.version = "C4";
|
||||
p1.description = "";
|
||||
p1.filePath = "[SAMPLE]";
|
||||
m_procedureList.append(p1);
|
||||
|
||||
ProcedureSummary p2;
|
||||
p2.id = "SIMPLE63";
|
||||
p2.name = "范例 一回路温度传感器绝缘和连续性检查 TP RCP63";
|
||||
p2.version = "SIMPLE";
|
||||
p2.description = "";
|
||||
p2.filePath = "[SAMPLE]";
|
||||
m_procedureList.append(p2);
|
||||
|
||||
ProcedureSummary p3;
|
||||
p3.id = "SIMPLE_TEST";
|
||||
p3.name = "简单测试规程";
|
||||
p3.version = "1.0";
|
||||
p3.description = "这是一个简单的测试规程,用于演示 ProcedurePlayer 的基本功能。包含一个测试任务组和结果展示。";
|
||||
p3.filePath = "[SAMPLE]";
|
||||
m_procedureList.append(p3);
|
||||
|
||||
// 也添加异常数据
|
||||
createMockExceptionData();
|
||||
}
|
||||
|
||||
void ProcedureManager::createMockExceptionData()
|
||||
{
|
||||
ProcedureSummary p7;
|
||||
p7.id = "EMPTY_DESC";
|
||||
p7.name = "空描述测试";
|
||||
p7.version = "1.0";
|
||||
p7.description = "";
|
||||
p7.filePath = "[MOCK_EXCEPTION]";
|
||||
m_procedureList.append(p7);
|
||||
|
||||
// Mock 异常数据 - 超长描述
|
||||
ProcedureSummary p8;
|
||||
p8.id = "LONG_DESC";
|
||||
p8.name = "超长描述测试";
|
||||
p8.version = "2.0";
|
||||
p8.description = "这是一个包含超长描述的测试规程,用于验证当描述文本过长时,界面能否正确处理和显示。"
|
||||
"描述内容可能包含多个段落、技术细节、注意事项等。在实际应用中,规程描述可能会非常详细,"
|
||||
"包括前置条件、执行步骤概述、预期结果、风险提示、相关文档引用等信息。这样的长描述需要"
|
||||
"界面能够适当地截断、折叠或提供滚动功能来确保用户体验。";
|
||||
p8.filePath = "[MOCK_EXCEPTION]";
|
||||
m_procedureList.append(p8);
|
||||
|
||||
// Mock 异常数据 - 数字和符号混合的 ID
|
||||
ProcedureSummary p9;
|
||||
p9.id = "TEST-2024-12-31_V1.0";
|
||||
p9.name = "日期版本号混合 ID";
|
||||
p9.version = "2024.12.31";
|
||||
p9.description = "测试复杂的 ID 和版本号格式";
|
||||
p9.filePath = "[MOCK_EXCEPTION]";
|
||||
m_procedureList.append(p9);
|
||||
|
||||
// Mock 异常数据 - 换行符
|
||||
ProcedureSummary p10;
|
||||
p10.id = "MULTILINE";
|
||||
p10.name = "多行\n文本\n测试";
|
||||
p10.version = "1.0";
|
||||
p10.description = "第一行描述\n第二行描述\n第三行描述";
|
||||
p10.filePath = "[MOCK_EXCEPTION]";
|
||||
m_procedureList.append(p10);
|
||||
}
|
||||
|
||||
StepType ProcedureManager::parseStepType(const QString &typeStr)
|
||||
{
|
||||
if (typeStr == "Manual")
|
||||
return StepType::Manual;
|
||||
if (typeStr == "Automatic")
|
||||
return StepType::Automatic;
|
||||
return StepType::Manual;
|
||||
}
|
||||
|
||||
StepStatus ProcedureManager::parseStepStatus(const QString &statusStr)
|
||||
{
|
||||
if (statusStr == "Pending")
|
||||
return StepStatus::Pending;
|
||||
if (statusStr == "InProgress")
|
||||
return StepStatus::InProgress;
|
||||
if (statusStr == "Confirmed")
|
||||
return StepStatus::Confirmed;
|
||||
if (statusStr == "Passed")
|
||||
return StepStatus::Passed;
|
||||
if (statusStr == "Failed")
|
||||
return StepStatus::Failed;
|
||||
if (statusStr == "Skipped")
|
||||
return StepStatus::Skipped;
|
||||
return StepStatus::Pending;
|
||||
}
|
||||
|
||||
ProcedureData ProcedureManager::loadMockProcedureFromJson(const QString &procedureId)
|
||||
{
|
||||
ProcedureData proc;
|
||||
proc.id = procedureId;
|
||||
proc.workOrderId = m_workOrderId;
|
||||
|
||||
// 尝试多个可能的 JSON 文件路径
|
||||
QStringList possiblePaths;
|
||||
possiblePaths << m_procedureDirectory + "/mock_procedures.json";
|
||||
possiblePaths << QDir::currentPath() + "/procedures/mock_procedures.json";
|
||||
possiblePaths << QCoreApplication::applicationDirPath() + "/procedures/mock_procedures.json";
|
||||
possiblePaths << QCoreApplication::applicationDirPath() + "/../../../procedures/mock_procedures.json";
|
||||
|
||||
QString jsonFilePath;
|
||||
for (const QString &path : possiblePaths)
|
||||
{
|
||||
if (QFile::exists(path))
|
||||
{
|
||||
jsonFilePath = path;
|
||||
qDebug() << "Found mock procedures JSON at:" << path;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (jsonFilePath.isEmpty())
|
||||
{
|
||||
qWarning() << "Mock procedures JSON file not found. Tried paths:" << possiblePaths;
|
||||
return proc;
|
||||
}
|
||||
|
||||
// 读取 JSON 文件
|
||||
QFile file(jsonFilePath);
|
||||
if (!file.open(QIODevice::ReadOnly))
|
||||
{
|
||||
qWarning() << "Failed to open mock procedures JSON:" << jsonFilePath;
|
||||
return proc;
|
||||
}
|
||||
|
||||
QByteArray jsonData = file.readAll();
|
||||
file.close();
|
||||
|
||||
QJsonDocument doc = QJsonDocument::fromJson(jsonData);
|
||||
if (!doc.isObject())
|
||||
{
|
||||
qWarning() << "Invalid JSON format in mock procedures file";
|
||||
return proc;
|
||||
}
|
||||
|
||||
QJsonObject root = doc.object();
|
||||
QJsonArray mockProcedures = root["mockProcedures"].toArray();
|
||||
|
||||
// 查找匹配的规程
|
||||
for (const QJsonValue &value : mockProcedures)
|
||||
{
|
||||
QJsonObject procObj = value.toObject();
|
||||
if (procObj["id"].toString() != procedureId)
|
||||
continue;
|
||||
|
||||
// 解析基本信息
|
||||
proc.name = procObj["name"].toString();
|
||||
proc.version = procObj["version"].toString();
|
||||
proc.description = procObj["description"].toString();
|
||||
|
||||
// 解析任务组
|
||||
QJsonArray taskGroupsArray = procObj["taskGroups"].toArray();
|
||||
for (const QJsonValue &groupValue : taskGroupsArray)
|
||||
{
|
||||
QJsonObject groupObj = groupValue.toObject();
|
||||
TaskGroup group;
|
||||
group.id = groupObj["id"].toString();
|
||||
group.name = groupObj["name"].toString();
|
||||
|
||||
// 解析步骤
|
||||
QJsonArray stepsArray = groupObj["steps"].toArray();
|
||||
for (const QJsonValue &stepValue : stepsArray)
|
||||
{
|
||||
QJsonObject stepObj = stepValue.toObject();
|
||||
StepData step;
|
||||
step.id = stepObj["id"].toString();
|
||||
step.content = stepObj["content"].toString();
|
||||
step.type = parseStepType(stepObj["type"].toString());
|
||||
step.status = parseStepStatus(stepObj["status"].toString());
|
||||
|
||||
// 解析表格引用
|
||||
if (stepObj.contains("tableRefs"))
|
||||
{
|
||||
QJsonArray tableRefsArray = stepObj["tableRefs"].toArray();
|
||||
for (const QJsonValue &refValue : tableRefsArray)
|
||||
{
|
||||
step.tableRefs.append(refValue.toString());
|
||||
}
|
||||
}
|
||||
|
||||
// 解析高亮字段
|
||||
if (stepObj.contains("highlightFields"))
|
||||
{
|
||||
QJsonArray highlightArray = stepObj["highlightFields"].toArray();
|
||||
for (const QJsonValue &fieldValue : highlightArray)
|
||||
{
|
||||
step.highlightFields.append(fieldValue.toString());
|
||||
}
|
||||
}
|
||||
|
||||
group.steps.append(step);
|
||||
}
|
||||
|
||||
proc.taskGroups.append(group);
|
||||
}
|
||||
|
||||
// 解析表格
|
||||
if (procObj.contains("tables"))
|
||||
{
|
||||
QJsonArray tablesArray = procObj["tables"].toArray();
|
||||
for (const QJsonValue &tableValue : tablesArray)
|
||||
{
|
||||
QJsonObject tableObj = tableValue.toObject();
|
||||
TableData table;
|
||||
table.id = tableObj["id"].toString();
|
||||
table.name = tableObj["name"].toString();
|
||||
if (tableObj.contains("description"))
|
||||
table.description = tableObj["description"].toString();
|
||||
|
||||
// 解析列
|
||||
if (tableObj.contains("columns"))
|
||||
{
|
||||
QJsonArray columnsArray = tableObj["columns"].toArray();
|
||||
for (const QJsonValue &colValue : columnsArray)
|
||||
{
|
||||
QJsonObject colObj = colValue.toObject();
|
||||
TableField field;
|
||||
field.id = colObj["id"].toString();
|
||||
field.name = colObj["name"].toString();
|
||||
field.type = colObj["type"].toString();
|
||||
if (colObj.contains("unit"))
|
||||
field.unit = colObj["unit"].toString();
|
||||
if (colObj.contains("isRequired"))
|
||||
field.isRequired = colObj["isRequired"].toBool();
|
||||
if (colObj.contains("isHighlighted"))
|
||||
field.isHighlighted = colObj["isHighlighted"].toBool();
|
||||
|
||||
table.columns.append(field);
|
||||
}
|
||||
}
|
||||
|
||||
proc.tables.append(table);
|
||||
}
|
||||
}
|
||||
|
||||
// 计算步骤统计
|
||||
if (procObj.contains("totalSteps"))
|
||||
{
|
||||
proc.totalSteps = procObj["totalSteps"].toInt();
|
||||
}
|
||||
else
|
||||
{
|
||||
proc.totalSteps = 0;
|
||||
for (const TaskGroup &group : proc.taskGroups)
|
||||
{
|
||||
proc.totalSteps += group.steps.size();
|
||||
}
|
||||
}
|
||||
|
||||
if (procObj.contains("completedSteps"))
|
||||
{
|
||||
proc.completedSteps = procObj["completedSteps"].toInt();
|
||||
}
|
||||
else
|
||||
{
|
||||
proc.completedSteps = 0;
|
||||
for (const TaskGroup &group : proc.taskGroups)
|
||||
{
|
||||
for (const StepData &step : group.steps)
|
||||
{
|
||||
if (step.status == StepStatus::Confirmed || step.status == StepStatus::Passed)
|
||||
{
|
||||
proc.completedSteps++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
qDebug() << "Loaded mock procedure from JSON:" << procedureId;
|
||||
break;
|
||||
}
|
||||
|
||||
return proc;
|
||||
}
|
||||
Reference in New Issue
Block a user