fix: refresh confirmed order pages and correct backup navigation
This commit is contained in:
parent
5cfc056c6b
commit
5c252fb272
@ -4476,6 +4476,11 @@ function loadPage(page) {
|
||||
});
|
||||
if (typeof loadSuppliers === 'function') loadSuppliers(1);
|
||||
}
|
||||
// 国内订单可能已被其他人确认;切回缓存页面时重新查询,保留当前筛选和页码。
|
||||
if (page === 'orders_domestic' && typeof domesticLoadOrders === 'function') {
|
||||
invalidateOrderColumnCache('domestic');
|
||||
domesticLoadOrders(domesticOrderPage || 1);
|
||||
}
|
||||
// 先销毁原有 Chart 实例(canvas detach 后 chart 可能状态错乱)
|
||||
if (typeof Chart !== 'undefined') {
|
||||
const canvases = cached.querySelectorAll('canvas');
|
||||
@ -16160,22 +16165,36 @@ function renderPendingConfirmModal(modal, item, bomMaterials, onConfirm) {
|
||||
}
|
||||
|
||||
function _refreshLinkedOrderLists() {
|
||||
// 只重新请求当前已挂载的订单表,沿用各自现有的筛选、表头筛选和页码状态。
|
||||
// 未挂载的页面容器仍可能保留下单前的数据,切回时必须重新加载。
|
||||
['orders_domestic', 'orders_overseas', 'orders_packaging', 'purchase_ready'].forEach(function(page) {
|
||||
var container = window._pageCache && window._pageCache[page];
|
||||
if (container && !container.isConnected) {
|
||||
delete window._pageCache[page];
|
||||
if (window._pageDataCache) delete window._pageDataCache[page];
|
||||
}
|
||||
});
|
||||
['domestic', 'overseas', 'packaging', 'backup'].forEach(function(type) {
|
||||
invalidateOrderColumnCache(type);
|
||||
});
|
||||
// 当前已挂载的订单表保留筛选和页码,立即重新请求。
|
||||
if (document.getElementById('domesticOrdersTbody') && typeof domesticLoadOrders === 'function') domesticLoadOrders(domesticOrderPage || 1);
|
||||
if (document.getElementById('overseasOrdersTbody') && typeof overseasLoadOrders === 'function') overseasLoadOrders(overseasOrderPage || 1);
|
||||
if (document.getElementById('packagingOrdersTbody') && typeof packagingLoadOrders === 'function') packagingLoadOrders(packagingOrderPage || 1);
|
||||
if (document.getElementById('orderTbody') && typeof loadBackupList === 'function') loadBackupList(false);
|
||||
}
|
||||
|
||||
function showConfirmRedirect(hasProduct, hasPackaging) {
|
||||
function showConfirmRedirect(hasProduct, hasPackaging, productPage) {
|
||||
var links = [];
|
||||
if (hasProduct) {
|
||||
links.push({ label: '📦 国内/海外订单管理', page: '/orders/domestic' });
|
||||
var overseas = productPage === 'orders_overseas';
|
||||
links.push({ label: overseas ? '📦 海外订单管理' : '📦 国内订单管理',
|
||||
page: overseas ? '/orders/overseas' : '/orders/domestic' });
|
||||
}
|
||||
if (hasPackaging) {
|
||||
links.push({ label: '📦 包材订单管理', page: '/orders/packaging' });
|
||||
}
|
||||
// 下单备份始终存在(已标记为ordered的记录)
|
||||
links.push({ label: '📋 下单备份管理', page: '/purchase' });
|
||||
links.push({ label: '📋 下单备份管理', page: '/purchase/ready' });
|
||||
|
||||
if (links.length === 0) return;
|
||||
|
||||
@ -16231,7 +16250,7 @@ function pendingBatchConfirm() {
|
||||
if (res.code === 0) {
|
||||
_refreshLinkedOrderLists();
|
||||
showCenteredAlert('操作成功', '✅ 批量下单成功,共 ' + checkedCodes.length + ' 个', function() {
|
||||
showConfirmRedirect(res.has_product_order, res.has_packaging_order);
|
||||
showConfirmRedirect(res.has_product_order, res.has_packaging_order, res.redirect);
|
||||
});
|
||||
loadPendingList();
|
||||
} else {
|
||||
@ -16323,7 +16342,7 @@ function pendingConfirmOrder(productCode) {
|
||||
_refreshLinkedOrderLists();
|
||||
showCenteredAlert('操作成功', '✅ 下单成功', {
|
||||
zIndex: 100000,
|
||||
onConfirm: function() { showConfirmRedirect(res.has_product_order, res.has_packaging_order); }
|
||||
onConfirm: function() { showConfirmRedirect(res.has_product_order, res.has_packaging_order, res.redirect); }
|
||||
});
|
||||
loadPendingList();
|
||||
} else {
|
||||
|
||||
110
tests/test_order_confirmation_navigation.js
Normal file
110
tests/test_order_confirmation_navigation.js
Normal file
@ -0,0 +1,110 @@
|
||||
/* Run with node: actual page functions in a minimal browser context. */
|
||||
const assert = require('node:assert/strict');
|
||||
const fs = require('node:fs');
|
||||
const path = require('node:path');
|
||||
const vm = require('node:vm');
|
||||
const source = fs.readFileSync(path.join(__dirname, '../static/js/app.js'), 'utf8');
|
||||
|
||||
function functionSource(start, end) {
|
||||
const offset = source.indexOf(start);
|
||||
assert.ok(offset >= 0, start);
|
||||
const finish = source.indexOf(end, offset);
|
||||
assert.ok(finish > offset, end);
|
||||
return source.slice(offset, finish);
|
||||
}
|
||||
|
||||
function context() {
|
||||
const calls = [];
|
||||
const overlays = [];
|
||||
const mainContent = {
|
||||
querySelectorAll: () => [],
|
||||
appendChild: element => { element.isConnected = true; }
|
||||
};
|
||||
const elements = { mainContent };
|
||||
const environment = {
|
||||
window: { _pageCache: {}, _pageDataCache: {}, _pageReloaders: {} },
|
||||
document: {
|
||||
getElementById: id => elements[id] || null,
|
||||
querySelectorAll: () => [],
|
||||
querySelector: () => null,
|
||||
createElement: () => ({ style: {}, innerHTML: '' }),
|
||||
body: { appendChild: element => overlays.push(element) }
|
||||
},
|
||||
domesticOrderPage: 3,
|
||||
overseasOrderPage: 2,
|
||||
packagingOrderPage: 4,
|
||||
domesticLoadOrders: page => calls.push(['domestic', page]),
|
||||
overseasLoadOrders: page => calls.push(['overseas', page]),
|
||||
packagingLoadOrders: page => calls.push(['packaging', page]),
|
||||
loadBackupList: reset => calls.push(['backup', reset]),
|
||||
invalidateOrderColumnCache: type => calls.push(['invalidate', type]),
|
||||
requestAnimationFrame: callback => callback(),
|
||||
setTimeout: callback => callback(),
|
||||
};
|
||||
vm.createContext(environment);
|
||||
vm.runInContext(functionSource('function _refreshLinkedOrderLists()', '// 防重复提交锁'), environment);
|
||||
vm.runInContext(functionSource('function loadPage(page)', '// ============ SPA 导航系统'), environment);
|
||||
return { environment, calls, overlays, elements };
|
||||
}
|
||||
|
||||
// Returning to a previously visited domestic order page queries current records,
|
||||
// even when the order was confirmed in another user's browser.
|
||||
{
|
||||
const { environment: env, calls } = context();
|
||||
const cached = { style: {}, isConnected: false, querySelectorAll: () => [] };
|
||||
env.window._pageCache.orders_domestic = cached;
|
||||
env.loadPage('orders_domestic');
|
||||
assert.equal(cached.isConnected, true);
|
||||
assert.deepEqual(calls, [['invalidate', 'domestic'], ['domestic', 3]]);
|
||||
}
|
||||
|
||||
// Confirming an order while its destination pages are detached removes their
|
||||
// old containers/data, while unrelated pages remain intact.
|
||||
{
|
||||
const { environment: env, calls } = context();
|
||||
const pages = ['orders_domestic', 'orders_overseas', 'orders_packaging', 'purchase_ready'];
|
||||
pages.forEach(page => {
|
||||
env.window._pageCache[page] = { isConnected: false };
|
||||
env.window._pageDataCache[page] = { old: true };
|
||||
});
|
||||
const unrelated = { isConnected: false };
|
||||
env.window._pageCache.planning = unrelated;
|
||||
env._refreshLinkedOrderLists();
|
||||
pages.forEach(page => {
|
||||
assert.equal(env.window._pageCache[page], undefined);
|
||||
assert.equal(env.window._pageDataCache[page], undefined);
|
||||
});
|
||||
assert.equal(env.window._pageCache.planning, unrelated);
|
||||
assert.deepEqual(calls, ['domestic', 'overseas', 'packaging', 'backup'].map(type => ['invalidate', type]));
|
||||
}
|
||||
|
||||
// A currently mounted list stays mounted and refreshes with its current page.
|
||||
{
|
||||
const { environment: env, elements, calls } = context();
|
||||
const current = { isConnected: true };
|
||||
env.window._pageCache.orders_domestic = current;
|
||||
elements.domesticOrdersTbody = {};
|
||||
env._refreshLinkedOrderLists();
|
||||
assert.equal(env.window._pageCache.orders_domestic, current);
|
||||
assert.deepEqual(calls.at(-1), ['domestic', 3]);
|
||||
}
|
||||
|
||||
// Finished-product navigation follows the server's route and the backup link
|
||||
// actually opens the backup menu rather than returning to pending orders.
|
||||
for (const [route, url] of [['orders_domestic', '/orders/domestic'], ['orders_overseas', '/orders/overseas']]) {
|
||||
const { environment: env, overlays } = context();
|
||||
env.showConfirmRedirect(true, false, route);
|
||||
const html = overlays[0].innerHTML;
|
||||
assert.ok(html.includes(`href="${url}"`));
|
||||
assert.ok(html.includes('href="/purchase/ready"'));
|
||||
assert.ok(!html.includes('href="/purchase"'));
|
||||
}
|
||||
|
||||
{
|
||||
const { environment: env, overlays } = context();
|
||||
env.showConfirmRedirect(false, true, null);
|
||||
assert.ok(overlays[0].innerHTML.includes('href="/orders/packaging"'));
|
||||
assert.ok(!overlays[0].innerHTML.includes('href="/orders/domestic"'));
|
||||
}
|
||||
|
||||
console.log('Order navigation regression tests passed (6 scenarios).');
|
||||
Loading…
x
Reference in New Issue
Block a user