Add optimization branch updates
This commit is contained in:
@@ -481,11 +481,11 @@ assert.match(
|
||||
);
|
||||
assert.match(
|
||||
inventoryLedgerSource,
|
||||
/source_doc_type: isProductionSurplusInbound\.value \? "WORK_ORDER" : null[\s\S]*source_doc_id: isProductionSurplusInbound\.value \? Number\(selectedGenericWorkOrder\.value\.work_order_id\) : null/
|
||||
/source_doc_type: isProductionSurplusInbound\.value \? "PRODUCTION_LEDGER" : null[\s\S]*source_doc_id: isProductionSurplusInbound\.value \? Number\(selectedGenericWorkOrder\.value\.production_ledger_id \|\| selectedGenericWorkOrder\.value\.work_order_id\) : null/
|
||||
);
|
||||
assert.match(
|
||||
inventoryLedgerSource,
|
||||
/source_doc_type: isProductionScrapInbound\.value \|\| isReworkScrapInbound\.value \? "WORK_ORDER" : activeWarehouseType\.value === "SEMI" \? "PRODUCT_ROUTE_OPERATION" : null[\s\S]*source_doc_id: isProductionScrapInbound\.value \|\| isReworkScrapInbound\.value \? Number\(selectedGenericWorkOrder\.value\.work_order_id\) : activeWarehouseType\.value === "SEMI" \? Number\(selectedSourceDocId \|\| 0\) : null/
|
||||
/source_doc_type: isProductionScrapInbound\.value \? "PRODUCTION_LEDGER" : isReworkScrapInbound\.value \? "WORK_ORDER" : activeWarehouseType\.value === "SEMI" \? "PRODUCT_ROUTE_OPERATION" : null[\s\S]*isProductionScrapInbound\.value[\s\S]*Number\(selectedGenericWorkOrder\.value\.production_ledger_id \|\| selectedGenericWorkOrder\.value\.work_order_id\)[\s\S]*isReworkScrapInbound\.value[\s\S]*Number\(selectedGenericWorkOrder\.value\.work_order_id\)/
|
||||
);
|
||||
assert.match(inventoryLedgerSource, /:key="`inventory-main-table-\$\{activeInventoryTab\}`"/);
|
||||
assert.match(inventoryLedgerSource, /:key="`inventory-controls-\$\{activeInventoryTab\}`"/);
|
||||
|
||||
@@ -0,0 +1,18 @@
|
||||
import assert from "node:assert/strict";
|
||||
import { readFileSync } from "node:fs";
|
||||
import path from "node:path";
|
||||
|
||||
const root = process.cwd();
|
||||
const source = readFileSync(path.join(root, "src/services/api.js"), "utf8");
|
||||
|
||||
assert.match(source, /\/auth\/login-key/, "login should fetch the backend public key before submitting");
|
||||
assert.match(source, /password_ciphertext/, "login payload should submit encrypted password ciphertext");
|
||||
assert.match(source, /login_key_id/, "login payload should include the public key id used for encryption");
|
||||
assert.doesNotMatch(
|
||||
source,
|
||||
/JSON\.stringify\(\{\s*username,\s*password\s*\}\)/,
|
||||
"login must not serialize the plaintext password field"
|
||||
);
|
||||
assert.doesNotMatch(source, /password:\s*password/, "login payload must not include plaintext password");
|
||||
|
||||
console.log("login password encryption checks passed");
|
||||
@@ -19,7 +19,7 @@ assert.match(
|
||||
|
||||
assert.match(
|
||||
source,
|
||||
/!isFinishedOutsourcingInbound && !isProductionScrapInbound && !isOutsourcingScrapInbound/,
|
||||
/!isFinishedOutsourcingInbound && !isProductionScrapInbound && !isReworkScrapInbound && !isOutsourcingScrapInbound/,
|
||||
"outsourcing scrap inbound should hide the manual lot number field"
|
||||
);
|
||||
|
||||
|
||||
@@ -10,7 +10,7 @@ const app = read("src/App.vue");
|
||||
const productionLedger = read("src/views/ProductionLedgerView.vue");
|
||||
const inventory = read("src/views/InventoryLedgerView.vue");
|
||||
|
||||
assert.match(router, /ProductionLedgerView/, "router should import ProductionLedgerView");
|
||||
assert.match(router, /component:\s*view\("ProductionLedgerView"\)/, "router should lazy load ProductionLedgerView");
|
||||
assert.match(router, /name:\s*"production-ledger"/, "router should expose production-ledger route");
|
||||
assert.match(router, /path:\s*"\/work-order-ledger"[\s\S]*redirect:\s*\{\s*name:\s*"production-ledger"\s*\}/, "old work-order-ledger route should redirect to production-ledger");
|
||||
assert.match(app, /生产台账/, "sidebar should show 生产台账");
|
||||
|
||||
@@ -15,12 +15,12 @@ const inventoryView = readSource("src/views/InventoryLedgerView.vue");
|
||||
|
||||
assert.match(
|
||||
router,
|
||||
/import\s+ProductionLedgerView\s+from\s+"..\/views\/ProductionLedgerView\.vue";/,
|
||||
"router should import ProductionLedgerView"
|
||||
/component:\s*view\("ProductionLedgerView"\)/,
|
||||
"router should lazy load ProductionLedgerView"
|
||||
);
|
||||
assert.match(
|
||||
router,
|
||||
/path:\s*"\/production-ledger"[\s\S]*?name:\s*"production-ledger"[\s\S]*?component:\s*ProductionLedgerView[\s\S]*?permission:\s*"MENU_WORK_ORDER"/,
|
||||
/path:\s*"\/production-ledger"[\s\S]*?name:\s*"production-ledger"[\s\S]*?component:\s*view\("ProductionLedgerView"\)[\s\S]*?permission:\s*"MENU_WORK_ORDER"/,
|
||||
"router should define production-ledger route with MENU_WORK_ORDER permission"
|
||||
);
|
||||
assert.match(
|
||||
|
||||
@@ -31,7 +31,7 @@ assert.match(
|
||||
|
||||
assert.match(
|
||||
source,
|
||||
/ref="salesOrderPickerRef"\s+class="order-tag-picker"\s+@pointerdown\.stop\s+@mousedown\.stop\s+@click\.stop/,
|
||||
/ref="salesOrderPickerRef"[\s\S]*class="[^"]*\border-tag-picker\b[^"]*"[\s\S]*@pointerdown\.stop[\s\S]*@mousedown\.stop[\s\S]*@click\.stop/,
|
||||
"sales order picker should keep internal clicks from bubbling into unrelated close handlers"
|
||||
);
|
||||
|
||||
|
||||
@@ -10,7 +10,11 @@ assert.doesNotMatch(source, /YL-NB|buildDefaultLotNo/, "purchase receipt UI must
|
||||
assert.doesNotMatch(source, /送货单号|supplier_delivery_no/, "purchase receipt UI should not keep the duplicate supplier delivery number field");
|
||||
assert.match(source, /后端自动生成库存批次号|系统自动生成库存批次号/, "purchase receipt UI should explain that inventory lot numbers are generated by the backend");
|
||||
assert.match(source, /uploadResource/, "purchase receipt UI should upload logistics auxiliary photos");
|
||||
assert.match(source, /selectedPurchaseTargetType\s*===\s*["']RAW["'][\s\S]*运单号[\s\S]*辅助照片/, "raw purchase receipt UI should show waybill and auxiliary photo fields");
|
||||
assert.match(
|
||||
source,
|
||||
/if\s*\(\s*selectedPurchaseTargetType\.value\s*===\s*["']RAW["']\s*\)\s*\{[\s\S]*key:\s*["']waybill_no["'][\s\S]*label:\s*["']运单号["'][\s\S]*key:\s*["']order_photo["'][\s\S]*label:\s*["']辅助照片["']/,
|
||||
"raw purchase receipt UI should show waybill and auxiliary photo fields"
|
||||
);
|
||||
assert.match(source, /validateLogisticsForm\s*\(\s*\)/, "raw purchase receipt submit should validate logistics information before posting");
|
||||
assert.match(source, /waybill_no:\s*selectedPurchaseTargetType\.value\s*===\s*["']RAW["']\s*\?\s*form\.waybill_no/, "purchase receipt payload should include raw waybill number");
|
||||
assert.match(source, /order_photo_url:\s*selectedPurchaseTargetType\.value\s*===\s*["']RAW["']\s*\?\s*form\.order_photo_url/, "purchase receipt payload should include raw auxiliary photo URL");
|
||||
|
||||
@@ -11,7 +11,7 @@ const requiredInventorySnippets = [
|
||||
"返工废料入库",
|
||||
"reworkScrapInbound",
|
||||
"isReworkScrapInbound",
|
||||
"source_doc_type: isProductionScrapInbound.value || isReworkScrapInbound.value ? \"WORK_ORDER\"",
|
||||
"source_doc_type: isProductionScrapInbound.value ? \"PRODUCTION_LEDGER\" : isReworkScrapInbound.value ? \"WORK_ORDER\"",
|
||||
"inbound_qty: inboundQty"
|
||||
];
|
||||
|
||||
|
||||
@@ -0,0 +1,29 @@
|
||||
import assert from "node:assert/strict";
|
||||
import { readFileSync } from "node:fs";
|
||||
|
||||
const routerSource = readFileSync(new URL("../src/router/index.js", import.meta.url), "utf8");
|
||||
|
||||
assert.doesNotMatch(
|
||||
routerSource,
|
||||
/import\s+\w+View\s+from\s+"..\/views\/[^"]+\.vue";/,
|
||||
"router should not statically import view components into the initial bundle"
|
||||
);
|
||||
|
||||
assert.match(
|
||||
routerSource,
|
||||
/import\.meta\.glob\("\.\.\/views\/\*\.vue"\)/,
|
||||
"router should register lazy view modules with Vite import.meta.glob"
|
||||
);
|
||||
|
||||
for (const viewName of [
|
||||
"LoginView",
|
||||
"DashboardView",
|
||||
"InventoryLedgerView",
|
||||
"PurchaseOrderView",
|
||||
"ProductionLedgerView",
|
||||
"SystemPermissionView"
|
||||
]) {
|
||||
assert.match(routerSource, new RegExp(`component:\\s*view\\("${viewName}"\\)`), `${viewName} route should use lazy view loader`);
|
||||
}
|
||||
|
||||
console.log("router lazy loading static checks passed");
|
||||
@@ -1,9 +1,7 @@
|
||||
import assert from "node:assert/strict";
|
||||
import { readFileSync } from "node:fs";
|
||||
import { resolve } from "node:path";
|
||||
|
||||
const appVuePath = resolve("frontend/src/App.vue");
|
||||
const source = readFileSync(appVuePath, "utf8");
|
||||
const source = readFileSync(new URL("../src/App.vue", import.meta.url), "utf8");
|
||||
|
||||
const navStart = source.indexOf("const navStages = [");
|
||||
const navEnd = source.indexOf("\n];", navStart);
|
||||
|
||||
@@ -139,13 +139,19 @@ const styleSource = readFileSync(
|
||||
fileURLToPath(new URL("../src/styles/main.css", import.meta.url)),
|
||||
"utf8"
|
||||
);
|
||||
const stocktakeDiffModalStart = styleSource.indexOf(".stocktake-diff-modal {");
|
||||
const stocktakeDiffModalEnd = styleSource.indexOf("\n}", stocktakeDiffModalStart);
|
||||
assert.notEqual(stocktakeDiffModalStart, -1);
|
||||
assert.notEqual(stocktakeDiffModalEnd, -1);
|
||||
const stocktakeDiffModalBlock = styleSource.slice(stocktakeDiffModalStart, stocktakeDiffModalEnd + 2);
|
||||
|
||||
assert.match(styleSource, /\.stocktake-diff-modal \.stocktake-diff-table-v2[\s\S]*margin: 14px 18px 0;/);
|
||||
assert.match(styleSource, /\.stocktake-diff-modal \.stocktake-footer[\s\S]*min-height: 72px;/);
|
||||
assert.match(styleSource, /\.stocktake-diff-modal-mask[\s\S]*box-sizing: border-box;/);
|
||||
assert.match(styleSource, /\.stocktake-diff-modal-mask[\s\S]*z-index: 3;/);
|
||||
assert.match(styleSource, /\.stocktake-diff-modal[\s\S]*height: min\(820px, 100%\);/);
|
||||
assert.match(styleSource, /\.stocktake-diff-modal[\s\S]*max-height: 100%;/);
|
||||
assert.doesNotMatch(styleSource, /\.stocktake-diff-modal[\s\S]*calc\(100vh - 64px\)/);
|
||||
assert.match(stocktakeDiffModalBlock, /height: min\(820px, 100%\);/);
|
||||
assert.match(stocktakeDiffModalBlock, /max-height: 100%;/);
|
||||
assert.doesNotMatch(stocktakeDiffModalBlock, /calc\(100vh - 64px\)/);
|
||||
assert.match(styleSource, /\.stocktake-diff-modal \.stocktake-footer[\s\S]*justify-content: flex-end;/);
|
||||
assert.match(styleSource, /\.stocktake-confirm-mask[\s\S]*z-index: 4;/);
|
||||
assert.match(styleSource, /\.stocktake-diff-cell,[\s\S]*overflow-wrap: anywhere;/);
|
||||
|
||||
@@ -18,8 +18,8 @@ assert.match(
|
||||
|
||||
assert.match(
|
||||
routerSource,
|
||||
/import SystemPermissionView from "\.\.\/views\/SystemPermissionView\.vue";/,
|
||||
"router should import SystemPermissionView"
|
||||
/component:\s*view\("SystemPermissionView"\)/,
|
||||
"router should lazy load SystemPermissionView"
|
||||
);
|
||||
assert.match(routerSource, /path:\s*"\/system-management"[\s\S]*redirect:/, "router should add /system-management redirect");
|
||||
assert.match(routerSource, /path:\s*"\/system-permissions"/, "router should add /system-permissions route");
|
||||
@@ -203,7 +203,7 @@ assert.doesNotMatch(
|
||||
);
|
||||
assert.match(
|
||||
systemPermissionSource,
|
||||
/function fitMindMapToScreen\(\)[\s\S]*mindMapFitRequestKey\.value \+= 1/,
|
||||
/async function requestMindMapFitToScreen[\s\S]*mindMapFitRequestKey\.value \+= 1[\s\S]*function fitMindMapToScreen\(\)\s*\{\s*requestMindMapFitToScreen\(\{ showToast: true, closeMenu: true \}\);/m,
|
||||
"one-screen fit action should request a viewport fit explicitly"
|
||||
);
|
||||
assert.match(systemPermissionSource, /const updatePayload\s*=/, "org edit must build an update-only payload");
|
||||
|
||||
@@ -0,0 +1,40 @@
|
||||
import assert from "node:assert/strict";
|
||||
import { readFileSync } from "node:fs";
|
||||
|
||||
function read(path) {
|
||||
return readFileSync(new URL(`../${path}`, import.meta.url), "utf8");
|
||||
}
|
||||
|
||||
function ruleBlock(source, selector) {
|
||||
const escaped = selector.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
||||
const match = source.match(new RegExp(`${escaped}\\s*\\{[\\s\\S]*?\\n\\}`, "m"));
|
||||
assert.ok(match, `Expected to find CSS block for ${selector}`);
|
||||
return match[0];
|
||||
}
|
||||
|
||||
function assertNoDeclaration(block, property) {
|
||||
assert.ok(!new RegExp(`\\b${property}\\s*:`, "m").test(block), `Unexpected ${property} declaration in:\n${block}`);
|
||||
}
|
||||
|
||||
const mainCss = read("src/styles/main.css");
|
||||
const purchaseOrderView = read("src/views/PurchaseOrderView.vue");
|
||||
const salesPlanningView = read("src/views/SalesPlanningView.vue");
|
||||
const orgMindMap = read("src/components/OrgMindMap.vue");
|
||||
|
||||
assertNoDeclaration(ruleBlock(mainCss, ".workflow-drawer"), "border-left");
|
||||
assertNoDeclaration(ruleBlock(mainCss, "body .login-console-frame"), "border-left");
|
||||
assertNoDeclaration(ruleBlock(purchaseOrderView, ".section-title"), "border-left");
|
||||
assertNoDeclaration(ruleBlock(salesPlanningView, ".section-title"), "border-left");
|
||||
assertNoDeclaration(ruleBlock(purchaseOrderView, ".purchase-decision-section"), "border-right");
|
||||
|
||||
assert.ok(
|
||||
!/transition:[^;]*(?:stroke-width|\br\s+[0-9.]+s)/.test(mainCss),
|
||||
"SVG DAG transitions should not animate stroke-width or radius-like r properties"
|
||||
);
|
||||
|
||||
assert.ok(
|
||||
!/transition:[^;]*(?:\bwidth\b|\bheight\b)/.test(orgMindMap),
|
||||
"Org mind map canvas should not animate width or height"
|
||||
);
|
||||
|
||||
console.log("ui antipattern guard ok");
|
||||
Reference in New Issue
Block a user