feat(admin): 店铺重复检查导出「站点」列改「国家」中文显示;撞款抽屉按点击处定位

- 导出 CSV 列头 站点→国家,值映射中文(DE德国/UK英国/FR法国/IT意大利/ES西班牙,未知回退原值)
- 撞款详情抽屉以触发元素为垂直锚点并钳制在视口内,不再贴区块/页面顶部导致看不见需上滑
- 同步 Java 静态托管副本;更新 Java/Python 相关断言
This commit is contained in:
2026-09-05 01:53:12 +08:00
parent d6086ec7b0
commit d3b499b596
5 changed files with 59 additions and 34 deletions
+19 -13
View File
@@ -2084,10 +2084,10 @@
return isNaN(t) ? -1 : t;
}
// 「查看明细」按钮点击开抽屉(动态元素,事件委托)
// 「查看明细」按钮点击开抽屉(动态元素,事件委托),并把被点按钮作为抽屉的垂直锚点
function handleDuplicateDetailClick(event) {
var button = event.target.closest('[data-open-asin-detail]');
if (button) openShopDataDuplicateDrawer(button.dataset.openAsinDetail);
if (button) openShopDataDuplicateDrawer(button.dataset.openAsinDetail, button);
}
// 站点徽章:中文国家(未识别回退原值)
@@ -2197,21 +2197,26 @@
}
// 图3 样式抽屉:ASIN + 店在售徽章 / 品牌行 / 彩色徽章组 / 按时间降序明细 + 次数列
// 块内定位:抽屉贴到「撞款详情」区块顶部(anchorRect),而不是浏览器左侧顶部;
// 区块滚出视口时钳制视口内可见区域(顶部矩阵点 ASIN 打开也要能看到抽屉)
// 块内定位:抽屉横向贴到「撞款详情」区块,纵向以触发元素(被点的 ASIN/「查看明细」按钮)为锚点、
// 钳制视口内,保证弹窗出现在点击处附近而非页面/滚动区顶部(顶部弹出会被当前滚动位置盖住看不见)。
var dupDrawerTriggerEl = null;
function positionDupDrawer() {
var mask = document.getElementById('dupCheckDrawerMask');
var aside = mask ? mask.querySelector('.drawer') : null;
var anchor = document.getElementById('dupCheckDetailBlock');
if (!aside || !anchor) return;
var rect = anchor.getBoundingClientRect();
var block = document.getElementById('dupCheckDetailBlock');
if (!aside || !block) return;
var bodyHeight = Math.max(document.documentElement.clientHeight, window.innerHeight);
var padTop = 24, padRight = 24, padBottom = 24;
var maxHeight = Math.max(260, bodyHeight - padTop - padBottom);
var left = Math.max(12, Math.min(rect.left + 12, Math.max(12, bodyWidth() - 860)));
var blockRect = block.getBoundingClientRect();
var left = Math.max(12, Math.min(blockRect.left + 12, Math.max(12, bodyWidth() - 860)));
// 垂直锚点优先取触发元素;未传入或已脱离文档时回退到「撞款详情」区块顶部
var anchor = (dupDrawerTriggerEl && dupDrawerTriggerEl.isConnected) ? dupDrawerTriggerEl : block;
var rect = anchor.getBoundingClientRect();
var top = Math.max(padTop, rect.top - padTop);
// 区块整体在视口外(下方/上方)时回退到视口顶部,避免抽屉出现在视口外
if (rect.top >= bodyHeight - 120 || rect.bottom <= padTop) top = padTop;
// 点击处整体已滚出视口下方时,改放到视口底部上方留出可读高度
if (rect.top >= bodyHeight - padBottom) top = Math.max(padTop, bodyHeight - 300);
// 顶部再钳制一次,保证抽屉头部可见
top = Math.min(top, Math.max(padTop, bodyHeight - 260));
aside.style.left = left + 'px';
@@ -2249,8 +2254,9 @@
return mask;
}
function openShopDataDuplicateDrawer(asin) {
function openShopDataDuplicateDrawer(asin, triggerEl) {
mountDupDrawerMaskToBody();
dupDrawerTriggerEl = triggerEl || null;
var item = null;
(shopDataDuplicateDetailItems || []).forEach(function (it) { if (it.asin === asin) item = it; });
if (!item) {
@@ -2738,10 +2744,10 @@
document.getElementById('dupCheckImportModal').onclick = function (event) {
if (event.target === this) closeDupCheckImportModal();
};
// 矩阵表格内 ASIN / 数字徽标点击打开抽屉(动态元素,事件委托)
// 矩阵表格内 ASIN / 数字徽标点击打开抽屉(动态元素,事件委托),并传入被点元素作为锚点
document.getElementById('shopDataDuplicateList').onclick = function (event) {
var target = event.target.closest('[data-open-drawer]');
if (target) openShopDataDuplicateDrawer(target.dataset.openDrawer);
if (target) openShopDataDuplicateDrawer(target.dataset.openDrawer, target);
};
// 撞款详情卡片区「查看明细」按钮(动态元素,事件委托)
document.getElementById('dupCheckDetailCards').onclick = handleDuplicateDetailClick;