feat(后台分组): 分组筛选与分组列仅超管可见,非超管一律隐藏

管理员/普通用户数据已由后端裁剪到本人可访问分组,分组维度对其无意义;
账号归属分组是超管职责,故只有超管需要按分组筛选与区分。

- 隐藏分组筛选+分组列:品牌数据库、查询ASIN、最低价ASIN、去重总数据、
  店铺管理、用户密钥
- 仅隐藏分组展示:店铺数据记录(筛选框+卡片行)、图片视频任务(所属分组行)、
  撞款检测(明细抽屉分组列+卡片分组标签)
- 弹窗分组选择保留展示但锁定:非超管仅1个可访问分组时自动选中并置灰
  (查询/最低价ASIN 另联动加载该分组店铺),多分组不锁以免限制用户
- 空数据行 colspan 随列显隐动态化
- 新增 tests/align-group-visibility.test.ts 回归守卫(5 条)
This commit is contained in:
2026-09-13 14:00:19 +08:00
parent 0323f0bb7b
commit 3f6ad0c6ad
10 changed files with 191 additions and 52 deletions
@@ -588,7 +588,7 @@ onMounted(() => {
<div class="dup-body">
<div v-for="block in shopBlocks(item)" :key="block.shopName" class="store-col">
<div class="st-name">{{ block.shopName }}<span class="st-count">{{ block.count }} 条</span></div>
<div v-if="block.groupName" class="st-grp">分组:{{ block.groupName }}</div>
<div v-if="isSuper && block.groupName" class="st-grp">分组:{{ block.groupName }}</div>
<template v-for="site in block.sites" :key="site.country">
<div class="c-site"><span class="m-dot" :style="{ background: siteColor(site.country) }"></span>{{ asinCountryLabel(site.country) }} · {{ site.times.length }} 次</div>
<div class="c-times"><span v-for="(time, index) in site.times" :key="index" class="c-time">{{ time }}</span></div>
@@ -666,12 +666,12 @@ onMounted(() => {
</div>
<table v-if="drawerAggRows.length" class="d-table">
<thead>
<tr><th>店铺</th><th>分组</th><th>站点</th><th>上架时间(按时间升序)</th><th>次数</th></tr>
<tr><th>店铺</th><th v-if="isSuper">分组</th><th>站点</th><th>上架时间(按时间升序)</th><th>次数</th></tr>
</thead>
<tbody>
<tr v-for="row in drawerRows" :key="row.shopName + '|' + row.country">
<td class="cell-strong">{{ row.shopName }}</td>
<td><span class="d-stgrp">{{ row.groupName || '—' }}</span></td>
<td v-if="isSuper"><span class="d-stgrp">{{ row.groupName || '—' }}</span></td>
<td><span class="site-chip" :style="{ background: siteColor(row.country) + '1F', color: siteColor(row.country) }">{{ asinCountryLabel(row.country || '') }}</span></td>
<td><template v-for="(time, index) in row.times" :key="index"><span class="d-time">{{ time }}</span></template></td>
<td class="num-cell">{{ row.count }}</td>