diff --git a/src/modules/iam/pages/InternalUsersView.test.ts b/src/modules/iam/pages/InternalUsersView.test.ts index d9e7a626..3832d088 100644 --- a/src/modules/iam/pages/InternalUsersView.test.ts +++ b/src/modules/iam/pages/InternalUsersView.test.ts @@ -93,6 +93,10 @@ describe('InternalUsersView unified platform user management', () => { expect(wrapper.text()).toContain('华远贸易') expect(wrapper.text()).toContain('租户管理员') expect(wrapper.text()).toContain('2026-06-01 10:30') + expect(wrapper.find('[aria-label="用户筛选"]').exists()).toBe(true) + expect(wrapper.find('[aria-label="用户列表"]').exists()).toBe(true) + expect(wrapper.text()).toContain('查询') + expect(wrapper.text()).toContain('重置') expect(wrapper.text()).not.toContain('认证用户 ID') expect(wrapper.text()).not.toContain('成员编号') }) diff --git a/src/modules/iam/pages/InternalUsersView.vue b/src/modules/iam/pages/InternalUsersView.vue index 5f964a70..38d94a11 100644 --- a/src/modules/iam/pages/InternalUsersView.vue +++ b/src/modules/iam/pages/InternalUsersView.vue @@ -16,6 +16,7 @@ import { getApiErrorDetails, getApiErrorMessage, type ApiErrorDetails } from '@/ import ApiErrorMeta from '@/shared/components/ApiErrorMeta.vue' import StatusBadge from '@/shared/components/StatusBadge.vue' import DataTable, { type DataTableColumn } from '@/shared/components/DataTable.vue' +import QueryToolbar, { type QueryField, type QueryModel } from '@/shared/components/QueryToolbar.vue' import { useUnsavedWorkRegistration } from '@/core/unsaved-work/useUnsavedWorkRegistration' import { useAccessPreviewStore } from '@/core/access/accessPreview' import { useAuthStore } from '@/core/auth/auth' @@ -33,7 +34,37 @@ const editingUser = ref(null) const rowActionId = ref('') const page = ref(1) const pageSize = ref(10) -const filters = reactive({ keyword: '', tenantId: '', status: '' }) +type UserFilters = QueryModel & { keyword: string; tenantId: string; status: string } +const filters = ref({ keyword: '', tenantId: '', status: '' }) +const appliedFilters = ref({ ...filters.value }) +const queryFields = computed(() => [ + { + key: 'keyword', + type: 'input', + placeholder: '用户名、姓名、手机号、租户或角色', + props: { maxlength: 128, 'aria-label': '用户关键词' }, + }, + { + key: 'tenantId', + type: 'select', + placeholder: '全部租户', + props: { 'aria-label': '所属租户' }, + options: options.value.tenants.map((tenant) => ({ + label: tenant.name, + value: String(tenant.id), + })), + }, + { + key: 'status', + type: 'select', + placeholder: '全部状态', + props: { 'aria-label': '用户状态' }, + options: [ + { label: '正常', value: 'ACTIVE' }, + { label: '禁用', value: 'DISABLED' }, + ], + }, +]) const emptyForm = () => ({ username: '', @@ -96,13 +127,13 @@ const formRules = computed(() => ({ })) const filteredRows = computed(() => { - const keyword = filters.keyword.trim().toLowerCase() + const keyword = appliedFilters.value.keyword.trim().toLowerCase() return users.value.filter((item) => { const matchesKeyword = !keyword || [item.username, item.displayName, item.phone ?? '', item.email ?? '', item.tenantName, ...item.roleNames] .some((value) => value.toLowerCase().includes(keyword)) return matchesKeyword - && (!filters.tenantId || String(item.tenantId) === filters.tenantId) - && (!filters.status || item.status === filters.status) + && (!appliedFilters.value.tenantId || String(item.tenantId) === appliedFilters.value.tenantId) + && (!appliedFilters.value.status || item.status === appliedFilters.value.status) }) }) const pagedRows = computed(() => filteredRows.value.slice((page.value - 1) * pageSize.value, page.value * pageSize.value)) @@ -247,10 +278,8 @@ function formatLogin(value: string | null) { return value.replace('T', ' ').slice(0, 16) } -function resetFilters() { - filters.keyword = '' - filters.tenantId = '' - filters.status = '' +function applyFilters() { + appliedFilters.value = { ...filters.value } page.value = 1 } @@ -266,26 +295,25 @@ onMounted(loadUsers) -
+ + +
-

用户管理 共 {{ filteredRows.length }} 条

+
+

用户列表 共 {{ filteredRows.length }} 条

+

统一维护平台与企业租户账号、所属角色和使用状态。

+
新增用户
-
- - - - - - - - - 重置 -
- + :loading="loading" :total="filteredRows.length" aria-label="用户列表" row-key="membershipId" empty-text="没有符合筛选条件的用户">