feat: align with upstream 1.5.9.9
This commit is contained in:
@@ -0,0 +1,103 @@
|
||||
import { createError, defineEventHandler, getQuery } from 'h3'
|
||||
import { db } from '~/drizzle/db'
|
||||
import { users, gradeClass } from '~/drizzle/schema'
|
||||
import { and, count, inArray, ne, notInArray } from 'drizzle-orm'
|
||||
import { smartSort } from '~~/server/utils/grade-class-core'
|
||||
import { ARCHIVED_USER_STATUSES, resolveArchivedFilter } from '~~/server/utils/user-archive'
|
||||
|
||||
export default defineEventHandler(async (event) => {
|
||||
try {
|
||||
// 检查用户是否为管理员
|
||||
const user = event.context.user
|
||||
|
||||
if (!user || !['ADMIN', 'SUPER_ADMIN'].includes(user.role)) {
|
||||
throw createError({
|
||||
statusCode: 403,
|
||||
message: '只有系统管理员可以访问此选项'
|
||||
})
|
||||
}
|
||||
|
||||
// 归档筛选:archived=1 仅查已归档(graduate/withdrawn);archived=0 排除已归档;缺省不限制
|
||||
const query = getQuery(event)
|
||||
const archivedFilter = resolveArchivedFilter(query.archived)
|
||||
|
||||
// 用户树需要全量轻字段,避免用分页列表推导时统计不完整;排除待审核用户(未通过审核不计入组织树/筛选)
|
||||
const treeConditions = [ne(users.status, 'pending')]
|
||||
if (archivedFilter === 'archived') {
|
||||
treeConditions.push(inArray(users.status, [...ARCHIVED_USER_STATUSES]))
|
||||
} else if (archivedFilter === 'unarchived') {
|
||||
treeConditions.push(notInArray(users.status, [...ARCHIVED_USER_STATUSES]))
|
||||
}
|
||||
|
||||
const treeUsers = await db
|
||||
.select({
|
||||
id: users.id,
|
||||
name: users.name,
|
||||
username: users.username,
|
||||
grade: users.grade,
|
||||
class: users.class,
|
||||
role: users.role,
|
||||
status: users.status
|
||||
})
|
||||
.from(users)
|
||||
.where(and(...treeConditions))
|
||||
|
||||
// 已归档用户总数(graduate/withdrawn 状态),供前端"已归档用户"入口徽标
|
||||
const archivedCountResult = await db
|
||||
.select({ count: count() })
|
||||
.from(users)
|
||||
.where(inArray(users.status, [...ARCHIVED_USER_STATUSES]))
|
||||
const archivedCount = archivedCountResult[0]?.count || 0
|
||||
|
||||
// 年级班级选项:配置优先;未配置时回退到全部用户聚合(含 withdrawn/graduate 与仅有班级项),
|
||||
// 与组织结构树口径一致,避免筛选下拉缺项
|
||||
const configRows = await db
|
||||
.select({ grade: gradeClass.grade, class: gradeClass.class })
|
||||
.from(gradeClass)
|
||||
|
||||
let grades: string[]
|
||||
let classes: { grade: string | null; class: string }[]
|
||||
if (configRows.length > 0) {
|
||||
const options = configRows
|
||||
.filter((item) => Boolean(item.grade?.trim()) && Boolean(item.class?.trim()))
|
||||
.sort((a, b) => {
|
||||
const gradeResult = smartSort(a.grade, b.grade)
|
||||
return gradeResult || smartSort(a.class, b.class)
|
||||
})
|
||||
grades = [...new Set(options.map((item) => item.grade))].sort(smartSort)
|
||||
classes = options.map((item) => ({ grade: item.grade, class: item.class }))
|
||||
} else {
|
||||
const gradesSet = new Set<string>()
|
||||
const classesMap = new Map<string, { grade: string | null; class: string }>()
|
||||
for (const treeUser of treeUsers) {
|
||||
const gradeValue = treeUser.grade?.trim() || ''
|
||||
const classValue = treeUser.class?.trim() || ''
|
||||
if (gradeValue) gradesSet.add(gradeValue)
|
||||
if (classValue) {
|
||||
const classKey = `${gradeValue}:${classValue}`
|
||||
if (!classesMap.has(classKey)) {
|
||||
classesMap.set(classKey, { grade: gradeValue || null, class: classValue })
|
||||
}
|
||||
}
|
||||
}
|
||||
grades = Array.from(gradesSet).sort(smartSort)
|
||||
classes = Array.from(classesMap.values()).sort((a, b) =>
|
||||
a.class.localeCompare(b.class, 'zh-CN', { numeric: true })
|
||||
)
|
||||
}
|
||||
|
||||
return {
|
||||
success: true,
|
||||
grades,
|
||||
classes,
|
||||
treeUsers,
|
||||
archivedCount
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('获取用户筛选选项失败:', error)
|
||||
throw createError({
|
||||
statusCode: 500,
|
||||
message: '获取选项失败'
|
||||
})
|
||||
}
|
||||
})
|
||||
Reference in New Issue
Block a user