From d15b09a0c9f3fd86eb58bb4199ea97d0a6650a4e Mon Sep 17 00:00:00 2001 From: zhangshun <453905631@qq.com> Date: Tue, 16 Jun 2026 10:36:34 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BC=98=E5=8C=96=E4=B8=9A=E5=8A=A1=E9=94=99?= =?UTF-8?q?=E8=AF=AF=E9=A1=B6=E5=B1=82=E5=93=8D=E5=BA=94?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- scripts/run_wasm_tests.js | 14 ++++++++- src/api/KinematicsWebAPI.Core.cpp | 42 ++++++++++++++++++++++++++- src/spc_core.cpp | 25 +++++++++++++++- tests/testdata/spc/invalid_count.json | 13 +++++++++ 4 files changed, 91 insertions(+), 3 deletions(-) create mode 100644 tests/testdata/spc/invalid_count.json diff --git a/scripts/run_wasm_tests.js b/scripts/run_wasm_tests.js index 7d76f48..e661740 100644 --- a/scripts/run_wasm_tests.js +++ b/scripts/run_wasm_tests.js @@ -366,6 +366,17 @@ const suite = [ { path: "res_data.Cpk.Cpk", gte: 0.1 }, ], }, + { + id: "spc_invalid_count", + type: "static", + requestFile: "tests/testdata/spc/invalid_count.json", + assertions: [ + { path: "success", equals: false }, + { path: "code", equals: 1000 }, + { path: "res_data.error", includes: "SPC calculation failed" }, + { path: "res_data.error", includes: "数据个数不匹配" }, + ], + }, { id: "fourbar_valid", type: "static", @@ -383,7 +394,8 @@ const suite = [ type: "static", requestFile: "tests/testdata/fourbar/crank_slider_invalid.json", assertions: [ - { path: "success", equals: true }, + { path: "success", equals: false }, + { path: "code", equals: 1000 }, { path: "res_data.success", equals: false }, { path: "res_data.error", includes: "Invalid parameters" }, { path: "res_data.validation_errors", lengthGte: 1 }, diff --git a/src/api/KinematicsWebAPI.Core.cpp b/src/api/KinematicsWebAPI.Core.cpp index 1b8f9a4..5b23684 100644 --- a/src/api/KinematicsWebAPI.Core.cpp +++ b/src/api/KinematicsWebAPI.Core.cpp @@ -22,6 +22,43 @@ bool isRobotCommand(const std::string &req_cmd) req_cmd == "Cmd_SelectCraftTree" || req_cmd == "Cmd_AddOperationTree"; } + +// 从业务返回体推导顶层 API 是否成功,避免把业务错误包装成成功响应。 +bool isBusinessResultSuccess(const json &res_data) +{ + if (!res_data.is_object()) + { + return true; + } + + if (res_data.contains("success") && res_data["success"].is_boolean()) + { + return res_data["success"].get(); + } + + return !res_data.contains("error"); +} + +// 提取业务错误信息,用于同步顶层 msg 字段。 +std::string getBusinessResultMessage(const json &res_data, const std::string &fallback) +{ + if (isBusinessResultSuccess(res_data)) + { + return fallback; + } + + if (res_data.contains("message") && res_data["message"].is_string()) + { + return res_data["message"].get(); + } + + if (res_data.contains("error") && res_data["error"].is_string()) + { + return res_data["error"].get(); + } + + return fallback.empty() ? "Business command failed" : fallback; +} } // namespace KinematicsWebAPI::KinematicsWebAPI() @@ -62,7 +99,10 @@ std::string KinematicsWebAPI::func(std::string sanitized_body) const json req_param = request_json.value("req_param", json::object()); json res_data = dispatchCommand(req_cmd, req_param); - return utils::create_api_response(true, 0, msg, req_code, req_from, req_cmd, res_data).dump(); + const bool business_success = isBusinessResultSuccess(res_data); + const int code = business_success ? 0 : 1000; + const std::string response_msg = getBusinessResultMessage(res_data, msg); + return utils::create_api_response(business_success, code, response_msg, req_code, req_from, req_cmd, res_data).dump(); } catch (const std::exception &e) { diff --git a/src/spc_core.cpp b/src/spc_core.cpp index 29eddd6..e1a44c0 100644 --- a/src/spc_core.cpp +++ b/src/spc_core.cpp @@ -703,9 +703,32 @@ json SpcCalculator::Spc(const json ¶m) // 使用测试数据 const std::vector &testData = req_param.x; // 改为小写 x int subgroupSize = req_param.n; + int subgroupCount = req_param.k; double usl = req_param.usl; double lsl = req_param.lsl; + if (subgroupSize < MIN_SUBGROUP_SIZE || subgroupSize > MAX_SUBGROUP_SIZE) + { + throw std::invalid_argument("子组大小 n 必须在 2 到 25 之间"); + } + + if (subgroupCount <= 0) + { + throw std::invalid_argument("子组个数 k 必须大于 0"); + } + + if (testData.empty()) + { + throw std::invalid_argument("测量数据 x 不能为空"); + } + + const size_t expectedDataCount = static_cast(subgroupSize) * static_cast(subgroupCount); + if (testData.size() != expectedDataCount) + { + throw std::invalid_argument("数据个数不匹配:期望 n*k=" + std::to_string(expectedDataCount) + + ",实际 x=" + std::to_string(testData.size())); + } + // 计算并获取整合的 JSON SpcDataXR xr = CalculateXR(testData, subgroupSize); SpcDataXS xs = CalculateXS(testData, subgroupSize); @@ -1419,4 +1442,4 @@ int main_spc() std::cerr << "错误: " << ex.what() << std::endl; return 1; } -} \ No newline at end of file +} diff --git a/tests/testdata/spc/invalid_count.json b/tests/testdata/spc/invalid_count.json new file mode 100644 index 0000000..69d776b --- /dev/null +++ b/tests/testdata/spc/invalid_count.json @@ -0,0 +1,13 @@ +{ + "msg": "spc invalid count", + "req_code": "CASE_SPC_INVALID_001", + "req_from": "wasm_test", + "req_cmd": "Cmd_Spc", + "req_param": { + "n": 5, + "k": 2, + "usl": 1.7, + "lsl": 1.5, + "x": [1.55, 1.58, 1.61, 1.6, 1.6] + } +}