CreoOtkPluging/MFCCreoDll.cpp
root 872a68d5be 实现Creo模型保存功能接口
新增功能:
- 添加SaveResult结构体用于保存操作结果
- 实现CreoManager::SaveModel()方法,使用OTK pfcModel::Save() API
- 添加SaveModelHandler HTTP路由处理器
- 注册/api/model/save接口支持POST请求

技术特性:
- 简化设计:只保存当前模型到原位置,无复杂另存为逻辑
- 完善的OTK异常处理:支持BadInputs、GeneralError、InvalidName等
- 标准JSON API格式:返回文件大小、保存时间、软件信息等
- 与现有架构完全兼容:不影响任何现有功能

API使用:
POST /api/model/save
请求: {"software_type": "creo"}
响应: 包含file_size、save_time、software、original_file等信息

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-07-21 19:46:22 +08:00

911 lines
37 KiB
C++
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

// MFCCreoDll.cpp: 定义 DLL 的初始化例程。
//
#include "pch.h"
#include "framework.h"
#include "MFCCreoDll.h"
#include "HttpServer.h"
#include "CreoManager.h"
#include <wfcSession.h>
#include <wfcGlobal.h>
#include <string>
#include <sstream>
#include <regex>
#include <mutex>
#include <atomic>
#include <memory>
#ifdef _DEBUG
#define new DEBUG_NEW
#endif
// --- 全局变量 ---
static std::unique_ptr<HttpServer> g_http_server;
static std::mutex message_mutex;
static std::string pending_message; // 待处理的消息
static std::atomic<bool> has_pending_message{false};
static UINT_PTR timer_id = 0;
// --- 辅助函数:将 std::string 转换为 xstring ---
xstring ConvertStringToXstring(const std::string& str)
{
std::wstring wstr(str.begin(), str.end());
return xstring(wstr.c_str());
}
// 定时器回调函数,在主线程中处理待处理的消息
VOID CALLBACK TimerProc(HWND hwnd, UINT uMsg, UINT_PTR idEvent, DWORD dwTime)
{
if (has_pending_message.load()) {
std::lock_guard<std::mutex> lock(message_mutex);
if (has_pending_message.load()) {
has_pending_message = false; // 立即清除标志,避免重复触发
try {
pfcSession_ptr Session = pfcGetCurrentSession();
if (Session) {
// 创建字符串序列
xstringsequence_ptr messages = xstringsequence::create();
messages->append(xstring("Hello World Test"));
Session->UIDisplayMessage("message.txt", "USER_INFO", messages);
}
}
catch (...) {
// 处理失败
}
}
}
}
// 测试路由处理器
HttpResponse TestHandler(const HttpRequest& request) {
bool creo_connected = false;
try {
pfcSession_ptr session = pfcGetCurrentSessionWithCompatibility(pfcC4Compatible);
creo_connected = (session != nullptr);
}
catch (...) {
creo_connected = false;
}
std::ostringstream json;
json << "{"
<< "\"success\": true,"
<< "\"data\": {"
<< "\"running\": " << (creo_connected ? "true" : "false") << ","
<< "\"message\": \"" << (creo_connected ? "CREOSON 与 Creo 均已启动" : "Creo 未连接") << "\""
<< "},"
<< "\"error\": null"
<< "}";
HttpResponse response;
response.body = json.str();
return response;
}
// 显示消息路由处理器
HttpResponse ShowMessageHandler(const HttpRequest& request) {
// 从查询参数获取消息
std::string message = "Default message";
size_t text_pos = request.query.find("text=");
if (text_pos != std::string::npos) {
text_pos += 5; // 跳过"text="
size_t end_pos = request.query.find("&", text_pos);
if (end_pos == std::string::npos) {
end_pos = request.query.length();
}
message = request.query.substr(text_pos, end_pos - text_pos);
}
// 设置待处理消息
{
std::lock_guard<std::mutex> lock(message_mutex);
pending_message = message;
has_pending_message = true;
}
HttpResponse response;
response.body = "{\"status\":\"ok\",\"message\":\"Message sent to Creo\"}";
return response;
}
// Creo状态检测路由处理器
HttpResponse CreoStatusHandler(const HttpRequest& request) {
CreoStatus status = CreoManager::Instance().GetCreoStatus();
std::ostringstream json;
json << "{"
<< "\"is_connected\":" << (status.is_connected ? "true" : "false") << ","
<< "\"version\":\"" << status.version << "\","
<< "\"build\":\"" << status.build << "\","
<< "\"working_directory\":\"" << status.working_directory << "\","
<< "\"session_id\":" << status.session_id
<< "}";
HttpResponse response;
response.body = json.str();
return response;
}
// 模型状态检测路由处理器
HttpResponse ModelStatusHandler(const HttpRequest& request) {
ModelStatus status = CreoManager::Instance().GetModelStatus();
std::ostringstream json;
if (status.has_model) {
json << "{"
<< "\"success\": true,"
<< "\"data\": {"
<< "\"name\": \"" << status.name << "\","
<< "\"filename\": \"" << status.filename << "\","
<< "\"type\": \"" << status.type << "\","
<< "\"software\": \"" << status.software << "\","
<< "\"version\": \"" << status.version << "\","
<< "\"connectionTime\": \"" << status.connection_time << "\","
<< "\"isAssembly\": " << (status.is_assembly ? "true" : "false") << ",";
if (status.is_assembly) {
json << "\"basicStats\": {"
<< "\"totalParts\": " << status.total_parts << ","
<< "\"assemblyLevels\": " << status.assembly_levels << ","
<< "\"fileSize\": \"" << status.file_size << "\""
<< "},";
}
json << "\"fileName\": \"" << status.filename << "\","
<< "\"sourceSoftware\": \"" << status.software << "\","
<< "\"partCount\": " << status.total_parts << ","
<< "\"assemblyLevel\": " << status.assembly_levels << ","
<< "\"connectionStatus\": \"" << status.connection_status << "\","
<< "\"openTime\": \"" << status.open_time << "\""
<< "},"
<< "\"error\": null"
<< "}";
} else {
json << "{"
<< "\"success\": false,"
<< "\"data\": null,"
<< "\"error\": \"No model is currently open\""
<< "}";
}
HttpResponse response;
response.body = json.str();
return response;
}
// 简单的JSON解析函数
std::string ExtractJsonValue(const std::string& json, const std::string& key) {
// 查找键值对 "key": "value"
std::string key_pattern = "\"" + key + "\"";
size_t key_pos = json.find(key_pattern);
if (key_pos != std::string::npos) {
// 找到冒号
size_t colon_pos = json.find(":", key_pos);
if (colon_pos != std::string::npos) {
// 跳过空格找到值的开始
size_t value_start = colon_pos + 1;
while (value_start < json.length() && (json[value_start] == ' ' || json[value_start] == '\t' || json[value_start] == '\n' || json[value_start] == '\r')) {
value_start++;
}
// 检查是否是字符串值(以双引号开始)
if (value_start < json.length() && json[value_start] == '"') {
size_t value_end = json.find('"', value_start + 1);
if (value_end != std::string::npos) {
return json.substr(value_start + 1, value_end - value_start - 1);
}
}
// 处理数字值(不以双引号开始)
else if (value_start < json.length()) {
size_t value_end = value_start;
while (value_end < json.length() &&
json[value_end] != ',' &&
json[value_end] != '}' &&
json[value_end] != ']' &&
json[value_end] != ' ' &&
json[value_end] != '\t' &&
json[value_end] != '\n' &&
json[value_end] != '\r') {
value_end++;
}
if (value_end > value_start) {
return json.substr(value_start, value_end - value_start);
}
}
}
}
return "";
}
bool ExtractJsonBool(const std::string& json, const std::string& key) {
std::regex pattern("\"" + key + "\"\s*:\s*(true|false)");
std::smatch match;
if (std::regex_search(json, match, pattern)) {
return match[1].str() == "true";
}
return false;
}
// 模型导出路由处理器
HttpResponse ExportModelHandler(const HttpRequest& request) {
if (request.method != "POST") {
HttpResponse response;
response.status_code = 405;
response.body = "{\"success\": false, \"error\": \"Method not allowed\"}";
return response;
}
// 解析JSON请求体
std::string software_type = ExtractJsonValue(request.body, "software_type");
std::string format_type = ExtractJsonValue(request.body, "format_type");
std::string export_path = ExtractJsonValue(request.body, "export_path");
// 提取options中的geom_flags - 简化处理,避免正则表达式崩溃
std::string geom_flags = "solids"; // 默认值
// 简单的字符串查找方式,避免正则表达式
size_t options_pos = request.body.find("\"options\"");
if (options_pos != std::string::npos) {
size_t start_brace = request.body.find("{", options_pos);
if (start_brace != std::string::npos) {
size_t end_brace = request.body.find("}", start_brace);
if (end_brace != std::string::npos) {
std::string options_content = request.body.substr(start_brace + 1, end_brace - start_brace - 1);
std::string extracted_geom_flags = ExtractJsonValue(options_content, "geom_flags");
if (!extracted_geom_flags.empty()) {
geom_flags = extracted_geom_flags;
}
}
}
}
// 验证参数
if (software_type != "creo" || format_type != "step" || export_path.empty()) {
HttpResponse response;
response.status_code = 400;
response.body = "{\"success\": false, \"error\": \"Invalid parameters\"}";
return response;
}
// 执行导出
ExportResult result = CreoManager::Instance().ExportModelToSTEP(export_path, geom_flags);
HttpResponse response;
if (result.success) {
std::ostringstream json;
json << "{"
<< "\"success\": true,"
<< "\"data\": {"
<< "\"exportPath\": \"" << result.export_path << "\","
<< "\"fileSize\": \"" << result.file_size << "\","
<< "\"format\": \"" << result.format << "\","
<< "\"exportTime\": \"" << result.export_time << "\","
<< "\"software\": \"" << result.software << "\","
<< "\"originalFile\": \"" << result.original_file << "\","
<< "\"details\": {"
<< "\"dirname\": \"" << result.dirname << "\","
<< "\"filename\": \"" << result.filename << "\","
<< "\"creoson_response\": {"
<< "\"dirname\": \"" << result.dirname << "\","
<< "\"filename\": \"" << result.filename << "\","
<< "\"full_path\": \"" << result.export_path << "\""
<< "}" // 结束 creoson_response
<< "}" // 结束 details
<< "}," // 结束 data
<< "\"error\": null"
<< "}";
response.body = json.str();
} else {
std::ostringstream json;
json << "{"
<< "\"success\": false,"
<< "\"data\": null,"
<< "\"error\": \"" << result.error_message << "\""
<< "}";
response.body = json.str();
response.status_code = 500;
}
return response;
}
// JSON字符串转义函数
std::string EscapeJsonString(const std::string& str) {
std::string escaped = str;
// 替换反斜杠
size_t pos = 0;
while ((pos = escaped.find("\\", pos)) != std::string::npos) {
escaped.replace(pos, 1, "\\\\");
pos += 2;
}
// 替换双引号
pos = 0;
while ((pos = escaped.find("\"", pos)) != std::string::npos) {
escaped.replace(pos, 1, "\\\"");
pos += 2;
}
// 替换换行符
pos = 0;
while ((pos = escaped.find("\n", pos)) != std::string::npos) {
escaped.replace(pos, 1, "\\n");
pos += 2;
}
// 替换制表符
pos = 0;
while ((pos = escaped.find("\t", pos)) != std::string::npos) {
escaped.replace(pos, 1, "\\t");
pos += 2;
}
return escaped;
}
// 层级分析路由处理器
HttpResponse HierarchyAnalysisHandler(const HttpRequest& request) {
HttpResponse response;
if (request.method != "POST") {
response.status_code = 405;
response.body = "{\"success\": false, \"error\": \"Method not allowed\"}";
return response;
}
try {
// 解析JSON请求
HierarchyAnalysisRequest analysis_request;
// 简单的JSON解析参考现有的ExtractJsonValue方法
analysis_request.software_type = ExtractJsonValue(request.body, "software_type");
analysis_request.project_name = ExtractJsonValue(request.body, "project_name");
analysis_request.include_geometry = ExtractJsonValue(request.body, "include_geometry") == "true";
// 解析max_depth参数保持兼容性但不实际使用
std::string max_depth_str = ExtractJsonValue(request.body, "max_depth");
if (!max_depth_str.empty()) {
try {
analysis_request.max_depth = std::stoi(max_depth_str);
} catch (...) {
analysis_request.max_depth = 0; // 0表示无限制
}
} else {
analysis_request.max_depth = 0; // 0表示无限制
}
// 执行层级分析
HierarchyAnalysisResult result = CreoManager::Instance().AnalyzeModelHierarchy(analysis_request);
if (result.success) {
// 构建成功响应
std::ostringstream json;
json << "{"
<< "\"success\": true,"
<< "\"message\": \"" << result.message << "\","
<< "\"data\": {"
<< "\"project_name\": \"" << EscapeJsonString(result.project_name) << "\","
<< "\"total_levels\": " << result.total_levels << ","
<< "\"total_components\": " << result.total_components << ","
<< "\"hierarchy\": [";
// 构建层级数据
for (size_t level = 0; level < result.hierarchy.size(); level++) {
if (level > 0) json << ",";
json << "{"
<< "\"level\": " << level << ","
<< "\"name\": \"" << (level == 0 ? "Main Assembly" :
level == 1 ? "Sub Assembly" :
level == 2 ? "Parts" :
"Level " + std::to_string(level + 1) + " Components") << "\","
<< "\"components\": [";
for (size_t comp = 0; comp < result.hierarchy[level].size(); comp++) {
if (comp > 0) json << ",";
const ComponentInfo& component = result.hierarchy[level][comp];
json << "{"
<< "\"id\": \"" << EscapeJsonString(component.id) << "\","
<< "\"name\": \"" << EscapeJsonString(component.name) << "\","
<< "\"type\": \"" << EscapeJsonString(component.type) << "\","
<< "\"level\": " << component.level << ","
<< "\"children_count\": " << component.children_count << ","
<< "\"path\": \"" << EscapeJsonString(component.full_path) << "\","
<< "\"file_size\": \"" << EscapeJsonString(component.file_size) << "\","
<< "\"deletion_safety\": \"" << EscapeJsonString(component.deletion_safety) << "\""
<< "}";
}
json << "]}";
}
json << "],"
<< "\"deletion_recommendations\": {"
<< "\"safe_deletions\": [],"
<< "\"risky_deletions\": [";
// 构建删除建议
for (size_t i = 0; i < result.risky_deletions.size(); i++) {
if (i > 0) json << ",";
const DeletionRecommendation& rec = result.risky_deletions[i];
json << "{"
<< "\"component_id\": \"" << EscapeJsonString(rec.component_id) << "\","
<< "\"component_name\": \"" << EscapeJsonString(rec.component_name) << "\","
<< "\"level\": " << rec.level << ","
<< "\"reason\": \"" << EscapeJsonString(rec.reason) << "\","
<< "\"risk_factors\": [";
for (size_t j = 0; j < rec.risk_factors.size(); j++) {
if (j > 0) json << ",";
json << "\"" << EscapeJsonString(rec.risk_factors[j]) << "\"";
}
json << "],"
<< "\"confidence\": " << rec.confidence
<< "}";
}
json << "]"
<< "}"
<< "}"
<< "}";
response.body = json.str();
} else {
// 构建失败响应
std::ostringstream json;
json << "{"
<< "\"success\": false,"
<< "\"data\": null,"
<< "\"error\": \"" << result.error_message << "\""
<< "}";
response.body = json.str();
response.status_code = 500;
}
} catch (const std::exception& e) {
response.status_code = 500;
response.body = "{\"success\": false, \"error\": \"JSON parsing error: " + std::string(e.what()) + "\"}";
} catch (...) {
response.status_code = 500;
response.body = "{\"success\": false, \"error\": \"Unknown error during hierarchy analysis\"}";
}
return response;
}
// 层级删除路由处理器
HttpResponse HierarchyDeleteHandler(const HttpRequest& request) {
HttpResponse response;
if (request.method != "POST") {
response.status_code = 405;
response.body = "{\"success\": false, \"error\": \"Method not allowed\"}";
return response;
}
try {
// 解析JSON请求
std::string software_type = ExtractJsonValue(request.body, "software_type");
std::string project_name = ExtractJsonValue(request.body, "project_name");
std::string target_level_str = ExtractJsonValue(request.body, "target_level");
if (software_type.empty() || project_name.empty() || target_level_str.empty()) {
response.status_code = 400;
response.body = "{\"success\": false, \"error\": \"Missing required parameters: software_type, project_name, target_level\"}";
return response;
}
int target_level;
try {
target_level = std::stoi(target_level_str);
} catch (...) {
response.status_code = 400;
response.body = "{\"success\": false, \"error\": \"Invalid target_level parameter\"}";
return response;
}
// 执行层级删除
CreoManager::HierarchyDeleteResult result = CreoManager::Instance().DeleteHierarchyComponents(project_name, target_level);
if (result.success) {
// 构建成功响应
std::ostringstream json;
json << "{"
<< "\"success\": true,"
<< "\"message\": \"" << EscapeJsonString(result.message) << "\","
<< "\"data\": {"
<< "\"original_levels\": " << result.original_levels << ","
<< "\"target_level\": " << result.target_level << ","
<< "\"final_levels\": " << result.final_levels << ","
<< "\"deleted_components\": {";
// 构建删除组件数据
bool first_level = true;
for (const auto& level_pair : result.deleted_components) {
if (!first_level) json << ",";
first_level = false;
json << "\"level_" << level_pair.first << "\": [";
bool first_component = true;
for (const auto& component : level_pair.second) {
if (!first_component) json << ",";
first_component = false;
json << "\"" << EscapeJsonString(component) << "\"";
}
json << "]";
}
json << "},"
<< "\"deletion_summary\": {"
<< "\"total_deleted\": " << result.total_deleted << ","
<< "\"successful\": " << result.successful << ","
<< "\"failed\": " << result.failed
<< "}"
<< "},"
<< "\"error\": null"
<< "}";
response.body = json.str();
} else {
// 构建错误响应
std::ostringstream json;
json << "{"
<< "\"success\": false,"
<< "\"message\": \"" << EscapeJsonString(result.message) << "\","
<< "\"error\": \"" << EscapeJsonString(result.error_message) << "\""
<< "}";
response.status_code = 500;
response.body = json.str();
}
} catch (const std::exception& e) {
response.status_code = 500;
response.body = "{\"success\": false, \"error\": \"JSON parsing error: " + std::string(e.what()) + "\"}";
} catch (...) {
response.status_code = 500;
response.body = "{\"success\": false, \"error\": \"Unknown error during hierarchy deletion\"}";
}
return response;
}
// 薄壳化分析处理器
HttpResponse ShellAnalysisHandler(const HttpRequest& request) {
HttpResponse response;
if (request.method != "POST") {
response.status_code = 405;
response.body = "{\"success\": false, \"error\": \"Method not allowed\"}";
return response;
}
try {
// 解析JSON请求参数
CreoManager::ShellAnalysisRequest analysis_request;
// 必填参数
analysis_request.software_type = ExtractJsonValue(request.body, "software_type");
if (analysis_request.software_type.empty()) {
response.status_code = 400;
response.body = "{\"success\": false, \"error\": \"Missing required parameter: software_type\"}";
return response;
}
if (analysis_request.software_type != "creo") {
response.status_code = 400;
response.body = "{\"success\": false, \"error\": \"Invalid software_type, must be 'creo'\"}";
return response;
}
// 可选参数解析
std::string project_name = ExtractJsonValue(request.body, "projectName");
if (!project_name.empty()) {
analysis_request.project_name = project_name;
}
std::string analysis_type = ExtractJsonValue(request.body, "analysisType");
if (!analysis_type.empty()) {
analysis_request.analysis_type = analysis_type;
}
std::string preserve_external = ExtractJsonValue(request.body, "preserveExternalSurfaces");
if (!preserve_external.empty()) {
analysis_request.preserve_external_surfaces = (preserve_external == "true");
}
std::string min_thickness = ExtractJsonValue(request.body, "minWallThickness");
if (!min_thickness.empty()) {
try {
analysis_request.min_wall_thickness = std::stod(min_thickness);
} catch (...) {
response.status_code = 400;
response.body = "{\"success\": false, \"error\": \"Invalid minWallThickness parameter\"}";
return response;
}
}
std::string confidence = ExtractJsonValue(request.body, "confidenceThreshold");
if (!confidence.empty()) {
try {
analysis_request.confidence_threshold = std::stod(confidence);
if (analysis_request.confidence_threshold < 0.0 || analysis_request.confidence_threshold > 1.0) {
response.status_code = 400;
response.body = "{\"success\": false, \"error\": \"confidenceThreshold must be between 0.0 and 1.0\"}";
return response;
}
} catch (...) {
response.status_code = 400;
response.body = "{\"success\": false, \"error\": \"Invalid confidenceThreshold parameter\"}";
return response;
}
}
// 执行薄壳化分析
CreoManager::ShellAnalysisResult result = CreoManager::Instance().AnalyzeShellFeatures(analysis_request);
if (result.success) {
// 构建成功响应
std::ostringstream json;
json << "{"
<< "\"success\": true,"
<< "\"data\": {"
<< "\"safeDeletions\": [";
// 构建安全删除列表
bool first_item = true;
for (const auto& deletion : result.safe_deletions) {
if (!first_item) json << ",";
first_item = false;
json << "{"
<< "\"id\": " << deletion.id << ","
<< "\"name\": \"" << EscapeJsonString(deletion.name) << "\","
<< "\"type\": \"" << EscapeJsonString(deletion.type) << "\","
<< "\"reason\": \"" << EscapeJsonString(deletion.reason) << "\","
<< "\"confidence\": " << deletion.confidence << ","
<< "\"volumeReduction\": " << deletion.volume_reduction;
if (!deletion.part_file.empty()) {
json << ",\"partFile\": \"" << EscapeJsonString(deletion.part_file) << "\"";
}
if (!deletion.part_path.empty()) {
json << ",\"partPath\": \"" << EscapeJsonString(deletion.part_path) << "\"";
}
json << ",\"componentType\": \"" << EscapeJsonString(deletion.component_type) << "\""
<< "}";
}
json << "],"
<< "\"suggestedDeletions\": [";
// 构建建议删除列表
first_item = true;
for (const auto& deletion : result.suggested_deletions) {
if (!first_item) json << ",";
first_item = false;
json << "{"
<< "\"id\": " << deletion.id << ","
<< "\"name\": \"" << EscapeJsonString(deletion.name) << "\","
<< "\"type\": \"" << EscapeJsonString(deletion.type) << "\","
<< "\"reason\": \"" << EscapeJsonString(deletion.reason) << "\","
<< "\"confidence\": " << deletion.confidence << ","
<< "\"volumeReduction\": " << deletion.volume_reduction
<< "}";
}
json << "],"
<< "\"preserveList\": [";
// 构建保留列表
first_item = true;
for (const auto& preserve : result.preserve_list) {
if (!first_item) json << ",";
first_item = false;
json << "{"
<< "\"id\": " << preserve.id << ","
<< "\"name\": \"" << EscapeJsonString(preserve.name) << "\","
<< "\"type\": \"" << EscapeJsonString(preserve.type) << "\","
<< "\"reason\": \"" << EscapeJsonString(preserve.reason) << "\","
<< "\"confidence\": " << preserve.confidence << ","
<< "\"volumeReduction\": " << preserve.volume_reduction
<< "}";
}
json << "],"
<< "\"estimatedReduction\": {"
<< "\"volumeReduction\": \"" << EscapeJsonString(result.estimated_reduction.volume_reduction) << "\","
<< "\"fileSizeReduction\": \"" << EscapeJsonString(result.estimated_reduction.file_size_reduction) << "\","
<< "\"performanceImprovement\": \"" << EscapeJsonString(result.estimated_reduction.performance_improvement) << "\""
<< "},"
<< "\"analysisParameters\": {"
<< "\"preserveExternalSurfaces\": " << (result.analysis_parameters.preserve_external_surfaces ? "true" : "false") << ","
<< "\"minWallThickness\": " << result.analysis_parameters.min_wall_thickness << ","
<< "\"confidenceThreshold\": " << result.analysis_parameters.confidence_threshold << ","
<< "\"totalFeatures\": " << result.analysis_parameters.total_features << ","
<< "\"deletableFeatures\": " << result.analysis_parameters.deletable_features << ","
<< "\"preservedFeatures\": " << result.analysis_parameters.preserved_features << ","
<< "\"assemblyAnalysis\": " << (result.analysis_parameters.assembly_analysis ? "true" : "false") << ","
<< "\"analysisStrategy\": \"" << EscapeJsonString(result.analysis_parameters.analysis_strategy) << "\","
<< "\"surfaceCount\": " << result.analysis_parameters.surface_count << ","
<< "\"shellSurfaces\": " << result.analysis_parameters.shell_surfaces << ","
<< "\"internalSurfaces\": " << result.analysis_parameters.internal_surfaces << ","
<< "\"shellFeatureWhitelist\": " << result.analysis_parameters.shell_feature_whitelist;
// 添加层次分析信息
if (result.analysis_parameters.hierarchy_analysis.enabled) {
json << ","
<< "\"hierarchyAnalysis\": {"
<< "\"enabled\": true,"
<< "\"totalParts\": " << result.analysis_parameters.hierarchy_analysis.total_parts << ","
<< "\"outerParts\": " << result.analysis_parameters.hierarchy_analysis.outer_parts << ","
<< "\"internalParts\": " << result.analysis_parameters.hierarchy_analysis.internal_parts << ","
<< "\"containmentRelationships\": " << result.analysis_parameters.hierarchy_analysis.containment_relationships << ","
<< "\"performanceStats\": {";
bool first_stat = true;
for (const auto& stat : result.analysis_parameters.hierarchy_analysis.performance_stats) {
if (!first_stat) json << ",";
first_stat = false;
json << "\"" << EscapeJsonString(stat.first) << "\": \"" << EscapeJsonString(stat.second) << "\"";
}
json << "}"
<< "}";
}
json << "}," // 结束 hierarchyAnalysis (加逗号)
<< "}," // 结束 analysisParameters (加逗号)
<< "\"error\": null"
<< "}";
response.body = json.str();
} else {
// 构建错误响应
std::ostringstream json;
json << "{"
<< "\"success\": false,"
<< "\"data\": null,"
<< "\"error\": \"" << EscapeJsonString(result.error_message) << "\""
<< "}";
response.status_code = 500;
response.body = json.str();
}
} catch (const std::exception& e) {
response.status_code = 500;
response.body = "{\"success\": false, \"data\": null, \"error\": \"JSON parsing error: " + std::string(e.what()) + "\"}";
} catch (...) {
response.status_code = 500;
response.body = "{\"success\": false, \"data\": null, \"error\": \"Unknown error during shell analysis\"}";
}
return response;
}
// 保存模型路由处理器
HttpResponse SaveModelHandler(const HttpRequest& request) {
HttpResponse response;
if (request.method != "POST") {
response.status_code = 405;
response.body = "{\"success\": false, \"error\": \"Method not allowed\"}";
return response;
}
try {
// 解析JSON请求参数
std::string software_type = ExtractJsonValue(request.body, "software_type");
// 参数验证
if (software_type.empty()) {
response.status_code = 400;
response.body = "{\"success\": false, \"error\": \"Missing required parameter: software_type\"}";
return response;
}
if (software_type != "creo") {
response.status_code = 400;
response.body = "{\"success\": false, \"error\": \"Invalid software_type, must be 'creo'\"}";
return response;
}
// 执行保存操作
SaveResult result = CreoManager::Instance().SaveModel();
if (result.success) {
// 构建成功响应
std::ostringstream json;
json << "{"
<< "\"success\": true,"
<< "\"data\": {"
<< "\"file_size\": \"" << EscapeJsonString(result.file_size) << "\","
<< "\"save_time\": \"" << EscapeJsonString(result.save_time) << "\","
<< "\"software\": \"" << EscapeJsonString(result.software) << "\","
<< "\"original_file\": \"" << EscapeJsonString(result.original_file) << "\""
<< "},"
<< "\"error\": null"
<< "}";
response.body = json.str();
} else {
// 构建错误响应
std::ostringstream json;
json << "{"
<< "\"success\": false,"
<< "\"data\": null,"
<< "\"error\": \"" << EscapeJsonString(result.error_message) << "\""
<< "}";
response.status_code = 500;
response.body = json.str();
}
} catch (const std::exception& e) {
response.status_code = 500;
response.body = "{\"success\": false, \"data\": null, \"error\": \"JSON parsing error: " + std::string(e.what()) + "\"}";
} catch (...) {
response.status_code = 500;
response.body = "{\"success\": false, \"data\": null, \"error\": \"Unknown error during save operation\"}";
}
return response;
}
extern "C" int user_initialize(
int argc,
char* argv[],
char* version,
char* build,
wchar_t errbuf[80])
{
pfcSession_ptr Session = pfcGetCurrentSessionWithCompatibility(pfcC4Compatible);
wfcWSession_ptr wSession = wfcWSession::cast(Session);
xstring info = L"New HTTP Server Starting on port 12345";
wSession->UIShowMessageDialog(info, NULL);
// 启动定时器处理消息
timer_id = SetTimer(NULL, 0, 100, TimerProc);
// 创建并启动HTTP服务器
g_http_server = std::make_unique<HttpServer>();
// 设置路由
g_http_server->SetRouteHandler("/test", TestHandler);
g_http_server->SetRouteHandler("/show_message", ShowMessageHandler);
g_http_server->SetRouteHandler("/api/status/creo", CreoStatusHandler);
g_http_server->SetRouteHandler("/api/status/model", ModelStatusHandler);
g_http_server->SetRouteHandler("/api/export/model", ExportModelHandler);
g_http_server->SetRouteHandler("/api/creo/analysis/hierarchy", HierarchyAnalysisHandler);
g_http_server->SetRouteHandler("/api/creo/hierarchy/delete", HierarchyDeleteHandler);
g_http_server->SetRouteHandler("/api/analysis/shell-analysis", ShellAnalysisHandler);
g_http_server->SetRouteHandler("/api/model/save", SaveModelHandler);
if (g_http_server->Start()) {
return 0;
} else {
g_http_server.reset();
return 1;
}
}
// --- OTK 出口函数 ---
// 这个函数在卸载插件或关闭 Creo 时被调用,非常重要!
extern "C" void user_terminate()
{
if (g_http_server) {
g_http_server->Stop();
g_http_server.reset();
}
if (timer_id != 0) {
KillTimer(NULL, timer_id);
timer_id = 0;
}
}