From 1b733b23b9c18d450a9da214a23a4c7e4ba41755 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=BB=84=E8=87=AA=E8=BE=BE?= <980324341@qq.com> Date: Sun, 13 Sep 2026 13:34:08 +0800 Subject: [PATCH] =?UTF-8?q?feat(=E5=AF=86=E9=92=A5=E7=AE=A1=E7=90=86):=20?= =?UTF-8?q?=E6=8C=89=E6=95=B0=E6=8D=AE=E6=9D=83=E9=99=90=E5=88=86=E7=BB=84?= =?UTF-8?q?=E9=9A=94=E7=A6=BB=E4=B8=8E=E7=AD=9B=E9=80=89?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 后台密钥列表改为按 biz_shop_manage_group 分组:主管只看自己带的分组成员,超管看全量可按 group_id 筛选 - 行数据补「所属分组」名称(批量查询);列表接口带回分组筛选项 - 修复超管筛选不生效:前端筛选参数统一 snake_case(camel 被后端静默忽略) - 列表列/筛选项文案由「所属管理员」改为「分组」 --- admin-frontend-vue/src/api/user-secrets.ts | 23 +-- .../src/pages/account/UserSecretsPage.vue | 46 +++--- .../shopkey/mapper/ShopManageGroupMapper.java | 33 +++++ .../shopkey/model/dto/UserGroupRef.java | 12 ++ .../AdminUserApiSecretController.java | 6 +- .../model/dto/AdminUserSecretQuery.java | 4 +- .../model/vo/AdminUserSecretPageVo.java | 7 + .../model/vo/AdminUserSecretRowVo.java | 8 +- .../service/UserApiSecretService.java | 133 ++++++++++++++---- .../service/UserApiSecretServiceTest.java | 75 +++++++--- 10 files changed, 251 insertions(+), 96 deletions(-) create mode 100644 backend-java/src/main/java/com/nanri/aiimage/modules/shopkey/model/dto/UserGroupRef.java diff --git a/admin-frontend-vue/src/api/user-secrets.ts b/admin-frontend-vue/src/api/user-secrets.ts index 1289dd54..411ca0a4 100644 --- a/admin-frontend-vue/src/api/user-secrets.ts +++ b/admin-frontend-vue/src/api/user-secrets.ts @@ -19,8 +19,8 @@ export interface AdminUserSecretModule { export interface AdminUserSecretRow { userId: number username: string - createdById: number | null - createdByUsername: string + /** 所属数据权限分组名(可能多个)。 */ + groups: string[] similarAsin: AdminUserSecretModule appearancePatent: AdminUserSecretModule proxy: AdminUserSecretModule @@ -34,26 +34,31 @@ export interface AdminUserSecretPage { total: number page: number pageSize: number + /** 分组筛选项(超管=全部;主管=自己带的分组)。 */ + groupOptions?: GroupOption[] } -/** 管理员下拉项(超管筛选用)。 */ -export interface AdminOption { +export interface GroupOption { id: number - username: string + groupName: string } export interface UserSecretQuery { keyword?: string checkStatus?: string - /** 按创建人筛选(仅超管生效)。 */ - createdById?: number + /** 按数据权限分组筛选(仅超管生效);后端参数为 snake_case。 */ + groupId?: number page: number pageSize: number } -/** 分页查询用户密钥(一行一用户):GET /api/admin/user-secrets */ +/** 分页查询用户密钥(一行一用户):GET /api/admin/user-secrets(筛选参数必须 snake_case,camel 会被后端静默忽略)。 */ export async function fetchUserSecretList(params: UserSecretQuery): Promise { - const { data } = await http.get('/api/admin/user-secrets', { params }) + const query: Record = { page: params.page, pageSize: params.pageSize } + if (params.keyword) query.keyword = params.keyword + if (params.checkStatus) query.checkStatus = params.checkStatus + if (params.groupId) query.group_id = params.groupId + const { data } = await http.get('/api/admin/user-secrets', { params: query }) return unwrap(data) } diff --git a/admin-frontend-vue/src/pages/account/UserSecretsPage.vue b/admin-frontend-vue/src/pages/account/UserSecretsPage.vue index 47a65f36..2bfa01ad 100644 --- a/admin-frontend-vue/src/pages/account/UserSecretsPage.vue +++ b/admin-frontend-vue/src/pages/account/UserSecretsPage.vue @@ -3,17 +3,15 @@ import { computed, onMounted, ref } from 'vue' import { ElMessage } from 'element-plus' import { formatDateTime } from '@/utils/datetime' import OldPagination from '@/components/OldPagination.vue' -import { useAdminSessionStore } from '@/stores/admin-session' -import { fetchUserList } from '@/api/users' import { checkUserSecret, deleteUserSecret, fetchUserSecretList, type AdminUserSecretModule, type AdminUserSecretRow, + type GroupOption, } from '@/api/user-secrets' -const session = useAdminSessionStore() const loading = ref(false) const rows = ref([]) const total = ref(0) @@ -21,9 +19,9 @@ const page = ref(1) const pageSize = ref(15) const keyword = ref('') const statusFilter = ref('') -const createdByIdFilter = ref(null) -/** 管理员下拉(仅超管可见/加载)。 */ -const adminOptions = ref>([]) +const groupFilter = ref(null) +/** 分组下拉(超管=全部;主管=自己带的分组,由列表接口带回)。 */ +const groupOptions = ref([]) /** 正在检测的行 userId,用于按钮 loading 态。 */ const checkingId = ref(null) @@ -91,28 +89,19 @@ function rowStatusTooltip(row: AdminUserSecretRow) { return parts.join(';') || '暂无检测记录' } -async function loadAdminOptions() { - if (!session.isSuperAdmin) return - try { - const result = await fetchUserList({ page: 1, pageSize: 999, role: 'admin' }) - adminOptions.value = result.admins || [] - } catch (error) { - console.warn('[user-secrets] 管理员下拉加载失败', error) - } -} - async function load() { loading.value = true try { const result = await fetchUserSecretList({ keyword: keyword.value.trim() || undefined, checkStatus: statusFilter.value || undefined, - createdById: createdByIdFilter.value || undefined, + groupId: groupFilter.value || undefined, page: page.value, pageSize: pageSize.value, }) rows.value = result?.items || [] total.value = Number(result?.total || 0) + groupOptions.value = result?.groupOptions || [] } catch (error) { ElMessage.error(error instanceof Error ? error.message : '加载失败') } finally { @@ -128,7 +117,7 @@ function search() { function reset() { keyword.value = '' statusFilter.value = '' - createdByIdFilter.value = null + groupFilter.value = null page.value = 1 load() } @@ -183,10 +172,7 @@ function changeSize(size: number) { load() } -onMounted(() => { - loadAdminOptions() - load() -}) +onMounted(load)