diff --git a/frontend/src/views/Settings.vue b/frontend/src/views/Settings.vue index 1c67323..756fa1b 100644 --- a/frontend/src/views/Settings.vue +++ b/frontend/src/views/Settings.vue @@ -421,16 +421,35 @@ />
- - - +
+ + + + + 未分配部门 + + {{ dept.deptName }} + + +
共 {{ filteredUsersList.length }} 位用户 @@ -3419,6 +3438,7 @@ const selectedUser = ref(null) const transferDeptId = ref(null) const allUsers = ref([]) const userManagementSearchKeyword = ref('') +const userManagementDeptFilter = ref() const offboardingPreviewLoading = ref(false) const offboardingExecuting = ref(false) const offboardingPreview = ref(null) @@ -3815,26 +3835,51 @@ const allUsersList = computed(() => { const filteredUsersList = computed(() => { const keyword = userManagementSearchKeyword.value.trim().toLowerCase() - if (!keyword) { - return allUsersList.value - } + const deptFilter = userManagementDeptFilter.value return allUsersList.value.filter((user) => { - const searchFields = [ + const matchesKeyword = !keyword || [ user.id, user.realName, user.username, user.phone, user.email, user.deptName - ] + ].some((field) => String(field || '').toLowerCase().includes(keyword)) - return searchFields.some((field) => - String(field || '').toLowerCase().includes(keyword) - ) + const matchesDept = !deptFilter + || (deptFilter === 'unassigned' + ? !user.deptId + : user.deptId === deptFilter) + + return matchesKeyword && matchesDept }) }) +const userManagementDepartmentOptions = computed(() => { + const seenDeptIds = new Set() + const options: Array<{ id: number; deptName: string }> = [] + + allUsersList.value.forEach((user) => { + if (!user.deptId || !user.deptName || seenDeptIds.has(user.deptId)) { + return + } + seenDeptIds.add(user.deptId) + options.push({ + id: user.deptId, + deptName: user.deptName + }) + }) + + return options.sort((a, b) => a.deptName.localeCompare(b.deptName)) +}) + +const filterUserDepartmentOption = (input: string, option: any) => { + const searchText = input.toLowerCase() + const optionLabel = String(option?.children || '').toLowerCase() + return optionLabel.includes(searchText) +} + // 格式化时间 const formatUserTime = (time: string | undefined) => { if (!time) return '--' @@ -6931,6 +6976,13 @@ watch(activeTab, (value) => { flex-wrap: wrap; } +.user-search-filters { + display: flex; + align-items: center; + gap: 12px; + flex-wrap: wrap; +} + .user-search-count { color: $text-tertiary; font-size: $font-size-sm;