From 4ac6b9034a5f81e583b23dab88318405cd73337c Mon Sep 17 00:00:00 2001 From: wikiboss Date: Thu, 17 Sep 2026 15:11:14 +0800 Subject: [PATCH] =?UTF-8?q?fix(order):=20=E4=BF=AE=E5=A4=8D=E8=AE=A2?= =?UTF-8?q?=E5=8D=95JS=E7=BC=BA=E5=B0=91=E9=97=AD=E5=90=88=E6=8B=AC?= =?UTF-8?q?=E5=8F=B7=E5=AF=BC=E8=87=B4=E8=AF=AD=E6=B3=95=E9=94=99=E8=AF=AF?= =?UTF-8?q?=E5=8F=8A=E9=A1=B5=E9=9D=A2=E6=89=93=E5=BC=80=E7=A9=BA=E7=99=BD?= =?UTF-8?q?=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../admin/controller/shopro/order/Order.php | 8 +- .../admin/view/shopro/order/order/index.html | 2 +- .../assets/js/backend/shopro/order/order.js | 2 + tests/verify_order_syntax_and_render.js | 92 +++++++++++++++++++ 4 files changed, 101 insertions(+), 3 deletions(-) create mode 100644 tests/verify_order_syntax_and_render.js diff --git a/application/admin/controller/shopro/order/Order.php b/application/admin/controller/shopro/order/Order.php index ad3f76a..ec3afe7 100644 --- a/application/admin/controller/shopro/order/Order.php +++ b/application/admin/controller/shopro/order/Order.php @@ -42,8 +42,12 @@ class Order extends Common if (!$this->request->isAjax()) { if (sheep_config('shop.platform.WechatMiniProgram.status')) { // 如果开启了小程序平台 // 设置小程序发货信息管理,消息通知跳转地址,有缓存, 不会每次都设置 - $uploadshoppingInfo = new \addons\shopro\library\easywechatPlus\WechatMiniProgramShop(Wechat::miniProgram()); - $uploadshoppingInfo->checkAndSetMessageJumpPath(); + try { + $uploadshoppingInfo = new \addons\shopro\library\easywechatPlus\WechatMiniProgramShop(Wechat::miniProgram()); + $uploadshoppingInfo->checkAndSetMessageJumpPath(); + } catch (\Throwable $e) { + \think\Log::error('WechatMiniProgram checkAndSetMessageJumpPath error: ' . $e->getMessage()); + } } $exportConfig = (new \addons\shopro\library\Export())->getConfig(); diff --git a/application/admin/view/shopro/order/order/index.html b/application/admin/view/shopro/order/order/index.html index 50d12e4..efbfc23 100644 --- a/application/admin/view/shopro/order/order/index.html +++ b/application/admin/view/shopro/order/order/index.html @@ -611,7 +611,7 @@ {if $auth->check('shopro/order/order/changeFee')} - 改价 {/if} diff --git a/public/assets/js/backend/shopro/order/order.js b/public/assets/js/backend/shopro/order/order.js index a038dc0..4715026 100644 --- a/public/assets/js/backend/shopro/order/order.js +++ b/public/assets/js/backend/shopro/order/order.js @@ -883,6 +883,8 @@ define(['jquery', 'bootstrap', 'backend', 'table', 'form'], function ($, undefin }, function (ret, res) { }) } }); + } + function onBack() { if (parent && parent.Layer && typeof parent.Layer.getFrameIndex === 'function') { try { diff --git a/tests/verify_order_syntax_and_render.js b/tests/verify_order_syntax_and_render.js new file mode 100644 index 0000000..3b77991 --- /dev/null +++ b/tests/verify_order_syntax_and_render.js @@ -0,0 +1,92 @@ +const fs = require('fs'); +const path = require('path'); +const vm = require('vm'); + +let passed = 0; +let failed = 0; + +function assert(condition, testName, detail = '') { + if (condition) { + console.log(` [PASS] ${testName}`); + passed++; + } else { + console.error(` [FAIL] ${testName} - ${detail}`); + failed++; + } +} + +console.log("========================================================"); +console.log(" 订单页面 JS 语法与模板渲染健壮性 TDD 自动化测试"); +console.log("========================================================\n"); + +// 1. 验证 order.js 文件存在与语法解析 +const orderJsPath = path.resolve(__dirname, '../public/assets/js/backend/shopro/order/order.js'); +assert(fs.existsSync(orderJsPath), 'order.js 文件存在'); + +const orderJsContent = fs.readFileSync(orderJsPath, 'utf-8'); + +// 语法检查 +let syntaxOk = false; +let syntaxErrorMsg = ''; +try { + new vm.Script(orderJsContent, { filename: 'order.js' }); + syntaxOk = true; +} catch (e) { + syntaxErrorMsg = e.message; +} +assert(syntaxOk, 'order.js 语法解析无 SyntaxError', syntaxErrorMsg); + +// 2. 验证 order.js 结构与闭合完整性 +const dummyDefine = function (deps, factory) { + const $ = () => ({}); + const Backend = { api: {} }; + const Table = {}; + const Form = {}; + return factory($, undefined, Backend, Table, Form); +}; + +let moduleLoaded = false; +let controllerObj = null; +try { + const sandbox = { + define: dummyDefine, + console: console, + location: { search: '?ref=addtabs' }, + window: {}, + Fast: { api: { ajax: () => {}, open: () => {}, fixurl: (u) => u } }, + Vue: { + ref: (v) => ({ value: v }), + reactive: (o) => o, + onMounted: () => {}, + getCurrentInstance: () => ({ proxy: { $refs: {} } }) + }, + createApp: () => {} + }; + vm.createContext(sandbox); + controllerObj = vm.runInContext(orderJsContent, sandbox); + if (controllerObj && typeof controllerObj.index === 'function' && typeof controllerObj.detail === 'function') { + moduleLoaded = true; + } +} catch (e) { + syntaxErrorMsg = e.message; +} +assert(moduleLoaded, 'order.js 成功执行并导出包含 index 和 detail 的 Controller 对象', syntaxErrorMsg); + +// 3. 验证 detail 中的 onConfirm 闭合与 onBack 独立存在 +const onConfirmPattern = /function onConfirm\(\)\s*\{[\s\S]*?proxy\.\$refs\['formRef'\]\.validate[\s\S]*?\}\);\s*\}\s*function onBack\(\)/; +assert(onConfirmPattern.test(orderJsContent), 'detail 中的 onConfirm 函数具有独立完整的闭合大括号,不侵入包裹后续方法'); + +// 4. 验证 index.html 模板中的按钮健壮性 +const orderIndexPath = path.resolve(__dirname, '../application/admin/view/shopro/order/order/index.html'); +assert(fs.existsSync(orderIndexPath), 'order/index.html 视图文件存在'); +const orderIndexContent = fs.readFileSync(orderIndexPath, 'utf-8'); + +const unsafeBtnMatch = orderIndexContent.includes('scope.row?.btns.includes'); +assert(!unsafeBtnMatch, 'order/index.html 中避免 scope.row?.btns.includes 引起的潜在 TypeError 崩溃'); + +console.log(`\n测试统计: 通过 ${passed}, 失败 ${failed}`); +if (failed > 0) { + process.exit(1); +} else { + process.exit(0); +}