align(查询ASIN): 回退参考纵向 rowspan 布局(序号/分组/店铺/操作合并+逐国ASIN行点击复制)、补新增ASIN弹窗(分组→店铺联动100/页聚合→国家→ASIN)、去更新时间列(对齐 admin.js renderQueryAsinRows/btnCreateQueryAsin/loadAsinShopNameOptions)

This commit is contained in:
2026-09-05 23:11:08 +08:00
parent 2f4bb834cf
commit 1848a34a27
4 changed files with 330 additions and 20 deletions
@@ -98,3 +98,51 @@ export function asinForCountry(item: QueryAsinItem, country: string): string {
export function queryAsinItemHasAnyAsin(item: QueryAsinItem): boolean {
return QUERY_ASIN_COUNTRIES.some((code) => asinForCountry(item, code) !== '')
}
/** 纵向行条目(对齐 admin.js renderQueryAsinEntries):按 DE/UK/FR/IT/ES 顺序收集有值国家;全空补一条空条目。 */
export interface QueryAsinRowEntry {
country: QueryAsinCountry | null
asin: string
}
export function queryAsinRowEntries(item: QueryAsinItem): QueryAsinRowEntry[] {
const entries: QueryAsinRowEntry[] = []
for (const code of QUERY_ASIN_COUNTRIES) {
const asin = asinForCountry(item, code)
if (asin) entries.push({ country: code, asin })
}
if (!entries.length) entries.push({ country: null, asin: '' })
return entries
}
/** 纵向展示行(对齐 admin.js renderQueryAsinRows):序号/分组/店铺/操作 按 rowspan 合并,逐国一行。 */
export interface QueryAsinDisplayRow {
key: string
rowNo: number
rowspan: number
isFirst: boolean
country: QueryAsinCountry | null
asin: string
item: QueryAsinItem
}
export function queryAsinDisplayRows(items: QueryAsinItem[], startRowNo: number): QueryAsinDisplayRow[] {
const out: QueryAsinDisplayRow[] = []
let rowNo = Math.max(Math.floor(startRowNo || 1), 1)
for (const item of items) {
const entries = queryAsinRowEntries(item)
entries.forEach((entry, index) => {
out.push({
key: `${item.id}:${index}`,
rowNo,
rowspan: entries.length,
isFirst: index === 0,
country: entry.country,
asin: entry.asin,
item,
})
})
rowNo += 1
}
return out
}