查询ASIN/最低价ASIN:精简新增弹窗
Build Backend JAR / build (push) Has been cancelled

- 国家由多选下拉改为单选,一次录入一个站点的 ASIN
- 店铺名改为按分组联动的下拉,移除带分页表格的「选择店铺」二级弹窗
- 表单压成两行(分组/店铺名/国家 + ASIN[/最低价]),按钮文案改为「保存」
- 保存成功后保留分组/店铺/国家,仅清空 ASIN 并聚焦,便于连续录入
- 清理随之失效的死代码:选择店铺弹窗 JS、按国家渲染输入框的 render/collect
  函数、.field-with-action/.skip-price-entry 等无引用 CSS
- admin.js 版本号改为 asin-create-v4,避免新 HTML 命中旧 JS 缓存

提交报文格式不变(countries:[code] + asin_mappings:{code:asin}),后端无需改动
This commit is contained in:
2026-09-01 13:39:50 +08:00
parent ac2b15d72f
commit f18d488cea
2 changed files with 155 additions and 485 deletions
+63 -161
View File
@@ -3687,10 +3687,7 @@
.table-ellipsis { display: block; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.asin-cell-content { min-width: 0; overflow: hidden; }
.asin-cell-meta { display: block; margin-top: 3px; color: #73869a; font-size: 12px; white-space: nowrap; }
.asin-empty-value, .asin-empty-hint { color: #8b9aaa; }
.skip-price-entry { display: grid !important; grid-template-columns: 58px minmax(0, 1fr) 140px; align-items: center; gap: 8px !important; }
.skip-price-country { color: var(--c-text-2); font-weight: 600; }
.skip-price-entry input { min-width: 0 !important; width: auto !important; }
.asin-empty-value { color: #8b9aaa; }
.asin-copy-text { display: block; max-width: 100%; margin: -3px 0 -3px -7px; padding: 3px 7px; border: 1px solid transparent; border-radius: var(--radius-sm); background: none; color: inherit; font: inherit; font-size: 13.5px; font-variant-numeric: tabular-nums; line-height: 1.5; text-align: left; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; cursor: pointer; }
.asin-copy-text:hover { border-color: #c7d7e5; background: #eef4fa; color: var(--c-primary-strong); }
.asin-copy-text:focus-visible { outline: 2px solid #4f78a5; outline-offset: 1px; }
@@ -3699,11 +3696,6 @@
th.asin-col-actions { z-index: 3; background: #f7f8fb; }
tbody tr:hover td.asin-col-actions { background: #f6f8fd; }
/* 表单里「输入框 + 附属按钮」组合,避免按钮溢出所在列挤掉列间距 */
.field-with-action { display: flex; align-items: center; gap: 8px; min-width: 0; }
.field-with-action > input, .field-with-action > select { flex: 1 1 auto; width: auto; }
.field-with-action > .btn { flex: 0 0 auto; white-space: nowrap; margin-top: 0; }
.visually-hidden { position: absolute; width: 1px; height: 1px; margin: -1px; padding: 0; border: 0; overflow: hidden; white-space: nowrap; clip: rect(0 0 0 0); clip-path: inset(50%); }
/* 菜单列表拖动排序 */
@@ -3747,24 +3739,10 @@
#panel-query-asin .panel-box > .form-row .form-group, #panel-skip-price-asin .panel-box > .form-row .form-group { min-width: 0; }
#panel-query-asin .panel-box > .form-row .btn, #panel-skip-price-asin .panel-box > .form-row .btn { justify-self: start; }
/* 新增 ASIN 表单行:分组/店铺名/国家/ASIN 字段 + 按钮同一行、同一底端基线。
轨道 min ≥ 组内自然宽(含「管理分组」等附属按钮),否则按钮挤出轨道挤乱间距 */
#panel-query-asin .form-box > .form-row:not([style]), #panel-skip-price-asin .form-box > .form-row:not([style]) { display: grid; grid-template-columns: minmax(190px, 1.05fr) minmax(220px, 1.2fr) minmax(150px, 0.85fr) minmax(300px, 1.55fr) auto; gap: 12px; align-items: end; }
#panel-query-asin .form-box > .form-row:not([style]) .form-group, #panel-skip-price-asin .form-box > .form-row:not([style]) .form-group { min-width: 0; width: auto; }
/* 新增按钮与输入框底端对齐(各组都是 label+输入框 等高结构,align-items:end 即对齐) */
#panel-query-asin .form-box > .form-row:not([style]) .btn, #panel-skip-price-asin .form-box > .form-row:not([style]) .btn { align-self: flex-end; margin: 0; white-space: nowrap; }
/* 输入框 + 附属按钮组合:允许在 grid 轨道内收缩(内联 min-width 会撑破轨道) */
#panel-query-asin .form-box > .form-row:not([style]) .field-with-action, #panel-skip-price-asin .form-box > .form-row:not([style]) .field-with-action { min-width: 0; }
#panel-query-asin .form-box > .form-row:not([style]) .field-with-action > input, #panel-skip-price-asin .form-box > .form-row:not([style]) .field-with-action > input,
#panel-query-asin .form-box > .form-row:not([style]) .field-with-action > select, #panel-skip-price-asin .form-box > .form-row:not([style]) .field-with-action > select { min-width: 0; }
@media (max-width: 1400px) {
/* 轨道最小值之和超出内容宽度时折两列(同 .dedupe-filter-row 的窄屏策略),ASIN 组与按钮跨整行 */
/* 轨道最小值之和超出内容宽度时折两列(同 .dedupe-filter-row 的窄屏策略),按钮跨整行 */
#panel-query-asin .panel-box > .form-row, #panel-skip-price-asin .panel-box > .form-row { grid-template-columns: repeat(2, minmax(150px, 1fr)); }
#panel-query-asin .form-box > .form-row:not([style]), #panel-skip-price-asin .form-box > .form-row:not([style]) { grid-template-columns: repeat(2, minmax(190px, 1fr)); }
#panel-query-asin .form-box > .form-row:not([style]) .form-group:nth-child(4), #panel-skip-price-asin .form-box > .form-row:not([style]) .form-group:nth-child(4) { grid-column: 1 / -1; }
#panel-query-asin .panel-box > .form-row .btn, #panel-skip-price-asin .panel-box > .form-row .btn,
#panel-query-asin .form-box > .form-row:not([style]) .btn, #panel-skip-price-asin .form-box > .form-row:not([style]) .btn { grid-column: 1 / -1; justify-self: start; }
#panel-query-asin .panel-box > .form-row .btn, #panel-skip-price-asin .panel-box > .form-row .btn { grid-column: 1 / -1; justify-self: start; }
}
.category-table-scroll .category-path-value { display: block; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
@@ -3812,10 +3790,7 @@
.admin-content { padding: 18px 14px 32px; }
.table-scroll { border-radius: 9px; }
.shop-manage-table-scroll > table, .category-table-scroll > table, .query-asin-table-scroll > table, .skip-price-asin-table-scroll > table { min-width: 920px; }
#panel-query-asin .panel-box > .form-row, #panel-skip-price-asin .panel-box > .form-row,
#panel-query-asin .form-box > .form-row:not([style]), #panel-skip-price-asin .form-box > .form-row:not([style]) { grid-template-columns: minmax(0, 1fr); align-items: stretch; }
.skip-price-entry { grid-template-columns: 56px minmax(0, 1fr); }
.skip-price-entry .skip-price-minimum-input { grid-column: 2; }
#panel-query-asin .panel-box > .form-row, #panel-skip-price-asin .panel-box > .form-row { grid-template-columns: minmax(0, 1fr); align-items: stretch; }
}
@@ -4927,45 +4902,6 @@
</div>
</div>
<!-- 编辑店铺管理弹窗 -->
<div class="modal-mask" id="chooseSkipPriceAsinShopModal" style="z-index:1100;">
<div class="modal" style="max-width:900px;width:90%;max-height:80vh;display:flex;flex-direction:column;">
<h3>选择店铺</h3>
<div class="form-row">
<div class="form-group" style="min-width:180px;">
<label>分组</label>
<select id="chooseSkipPriceAsinShopGroupId">
<option value="">全部分组</option>
</select>
</div>
<div class="form-group" style="min-width:220px;">
<label>店铺名</label>
<input type="text" id="chooseSkipPriceAsinShopKeyword" placeholder="请输入店铺名">
</div>
<button class="btn" id="btnSearchChooseSkipPriceAsinShop" type="button">查询</button>
</div>
<div style="flex:1;min-height:0;overflow:auto;">
<table>
<thead>
<tr>
<th>序号</th>
<th>分组</th>
<th>店铺名</th>
<th>店铺商城名</th>
<th>账号</th>
<th>操作</th>
</tr>
</thead>
<tbody id="chooseSkipPriceAsinShopListBody"></tbody>
</table>
</div>
<div class="pagination" id="chooseSkipPriceAsinShopPagination"></div>
<div style="margin-top:16px;display:flex;gap:8px;justify-content:flex-end;">
<button class="btn btn-secondary" id="btnCloseChooseSkipPriceAsinShopModal" type="button">关闭</button>
</div>
</div>
</div>
<div class="drawer-mask" id="skipPriceAsinDrawer">
<div class="drawer" role="dialog" aria-modal="true" aria-labelledby="skipPriceAsinDrawerTitle">
<div class="drawer-header">
@@ -4988,44 +4924,6 @@
</div>
</div>
<div class="modal-mask" id="chooseQueryAsinShopModal" style="z-index:1100;">
<div class="modal" style="max-width:900px;width:90%;max-height:80vh;display:flex;flex-direction:column;">
<h3>选择店铺</h3>
<div class="form-row">
<div class="form-group" style="min-width:180px;">
<label>分组</label>
<select id="chooseQueryAsinShopGroupId">
<option value="">全部分组</option>
</select>
</div>
<div class="form-group" style="min-width:220px;">
<label>店铺名</label>
<input type="text" id="chooseQueryAsinShopKeyword" placeholder="请输入店铺名">
</div>
<button class="btn" id="btnSearchChooseQueryAsinShop" type="button">查询</button>
</div>
<div style="flex:1;min-height:0;overflow:auto;">
<table>
<thead>
<tr>
<th>序号</th>
<th>分组</th>
<th>店铺名</th>
<th>店铺商城名</th>
<th>账号</th>
<th>操作</th>
</tr>
</thead>
<tbody id="chooseQueryAsinShopListBody"></tbody>
</table>
</div>
<div class="pagination" id="chooseQueryAsinShopPagination"></div>
<div style="margin-top:16px;display:flex;gap:8px;justify-content:flex-end;">
<button class="btn btn-secondary" id="btnCloseChooseQueryAsinShopModal" type="button">关闭</button>
</div>
</div>
</div>
<div class="drawer-mask" id="queryAsinDrawer">
<div class="drawer" role="dialog" aria-modal="true" aria-labelledby="queryAsinDrawerTitle">
<div class="drawer-header">
@@ -5349,39 +5247,44 @@
<div class="modal-mask" id="createSkipPriceAsinModal">
<div class="modal">
<h3>新增 ASIN</h3>
<div class="form-group">
<label>分组</label>
<select id="skipPriceAsinGroupSelect" style="min-width:200px;">
<option value="">请选择分组</option>
</select>
</div>
<div class="form-group">
<label>店铺名</label>
<div class="field-with-action">
<input type="text" id="skipPriceAsinShopName" placeholder="请输入店铺名称">
<button class="btn btn-secondary" id="btnChooseSkipPriceAsinShop" type="button">选择店铺</button>
<div class="form-row">
<div class="form-group">
<label for="skipPriceAsinGroupSelect">分组</label>
<select id="skipPriceAsinGroupSelect">
<option value="">请选择分组</option>
</select>
</div>
<div class="form-group">
<label for="skipPriceAsinShopName">店铺名</label>
<select id="skipPriceAsinShopName" disabled>
<option value="">请先选择分组</option>
</select>
</div>
<div class="form-group">
<label for="skipPriceAsinCountry">国家</label>
<select id="skipPriceAsinCountry">
<option value="">请选择国家</option>
<option value="DE">德国</option>
<option value="UK">英国</option>
<option value="FR">法国</option>
<option value="IT">意大利</option>
<option value="ES">西班牙</option>
</select>
</div>
</div>
<div class="form-group">
<label>国家</label>
<select id="skipPriceAsinCountries" class="js-dropdown-multi" multiple>
<option value="DE">德国</option>
<option value="UK">英国</option>
<option value="FR">法国</option>
<option value="IT">意大利</option>
<option value="ES">西班牙</option>
</select>
</div>
<div class="form-group">
<label id="skipPriceAsinInputsLabel">ASIN / 最低价</label>
<div id="skipPriceAsinInputs" role="group" aria-labelledby="skipPriceAsinInputsLabel"
style="display:flex;flex-direction:column;gap:8px;">
<div style="color:var(--c-text-3);font-size:13px;">请选择国家后输入对应 ASIN 和最低价</div>
<div class="form-row">
<div class="form-group">
<label for="skipPriceAsinValue">ASIN</label>
<input type="text" id="skipPriceAsinValue" placeholder="请输入 ASIN">
</div>
<div class="form-group" style="flex:0 0 180px;">
<label for="skipPriceAsinMinimumPrice">最低价</label>
<input type="number" id="skipPriceAsinMinimumPrice" min="0" step="0.01" placeholder="选填">
</div>
</div>
<p class="msg" id="msgSkipPriceAsin"></p>
<div style="margin-top:16px;display:flex;gap:8px;">
<button class="btn" id="btnCreateSkipPriceAsin">新增 ASIN</button>
<button class="btn" id="btnCreateSkipPriceAsin">保存</button>
<button class="btn btn-secondary" id="btnCloseCreateSkipPriceAsinModal" type="button">取消</button>
</div>
</div>
@@ -5447,39 +5350,38 @@
<div class="modal-mask" id="createQueryAsinModal">
<div class="modal">
<h3>新增查询 ASIN</h3>
<div class="form-group">
<label>分组</label>
<select id="queryAsinGroupSelect" style="min-width:200px;">
<option value="">请选择分组</option>
</select>
</div>
<div class="form-group">
<label>店铺名</label>
<div class="field-with-action">
<input type="text" id="queryAsinShopName" placeholder="请输入店铺名称">
<button class="btn btn-secondary" id="btnChooseQueryAsinShop" type="button">选择店铺</button>
<div class="form-row">
<div class="form-group">
<label for="queryAsinGroupSelect">分组</label>
<select id="queryAsinGroupSelect">
<option value="">请选择分组</option>
</select>
</div>
<div class="form-group">
<label for="queryAsinShopName">店铺名</label>
<select id="queryAsinShopName" disabled>
<option value="">请先选择分组</option>
</select>
</div>
<div class="form-group">
<label for="queryAsinCountry">国家</label>
<select id="queryAsinCountry">
<option value="">请选择国家</option>
<option value="DE">德国</option>
<option value="UK">英国</option>
<option value="FR">法国</option>
<option value="IT">意大利</option>
<option value="ES">西班牙</option>
</select>
</div>
</div>
<div class="form-group">
<label>国家</label>
<select id="queryAsinCountries" class="js-dropdown-multi" multiple>
<option value="DE">德国</option>
<option value="UK">英国</option>
<option value="FR">法国</option>
<option value="IT">意大利</option>
<option value="ES">西班牙</option>
</select>
</div>
<div class="form-group">
<label id="queryAsinInputsLabel">ASIN</label>
<div id="queryAsinInputs" role="group" aria-labelledby="queryAsinInputsLabel"
style="display:flex;flex-direction:column;gap:8px;">
<div style="color:var(--c-text-3);font-size:13px;">请选择国家后输入对应 ASIN</div>
</div>
<label for="queryAsinValue">ASIN</label>
<input type="text" id="queryAsinValue" placeholder="请输入 ASIN">
</div>
<p class="msg" id="msgQueryAsin"></p>
<div style="margin-top:16px;display:flex;gap:8px;">
<button class="btn" id="btnCreateQueryAsin">新增 ASIN</button>
<button class="btn" id="btnCreateQueryAsin">保存</button>
<button class="btn btn-secondary" id="btnCloseCreateQueryAsinModal" type="button">取消</button>
</div>
</div>
@@ -5654,7 +5556,7 @@
window.__initAdminMenuCollapse();
})();
</script>
<script src="/static/admin.js?v=admin-menu-v3"></script>
<script src="/static/admin.js?v=asin-create-v4"></script>
<div class="admin-toast-region" id="adminToastRegion" role="status" aria-live="polite" aria-atomic="true"></div>
<div class="admin-confirm-mask" id="adminConfirmModal" aria-hidden="true">
<section class="admin-confirm-dialog" role="alertdialog" aria-modal="true" aria-labelledby="adminConfirmTitle" aria-describedby="adminConfirmMessage">