228 lines
5.4 KiB
TypeScript
228 lines
5.4 KiB
TypeScript
![]() |
// 管理员用户管理API
|
|||
|
import { serverSupabaseClient, serverSupabaseUser } from '#supabase/server'
|
|||
|
|
|||
|
export default defineEventHandler(async (event) => {
|
|||
|
const supabase = await serverSupabaseClient(event)
|
|||
|
const user = await serverSupabaseUser(event)
|
|||
|
|
|||
|
if (!user) {
|
|||
|
throw createError({
|
|||
|
statusCode: 401,
|
|||
|
statusMessage: '未授权访问'
|
|||
|
})
|
|||
|
}
|
|||
|
|
|||
|
// 验证管理员权限
|
|||
|
const { data: profile } = await supabase
|
|||
|
.from('profiles')
|
|||
|
.select('role')
|
|||
|
.eq('id', user.id)
|
|||
|
.single()
|
|||
|
|
|||
|
if (!profile || profile.role !== 'admin') {
|
|||
|
throw createError({
|
|||
|
statusCode: 403,
|
|||
|
statusMessage: '权限不足,需要管理员权限'
|
|||
|
})
|
|||
|
}
|
|||
|
|
|||
|
const method = getMethod(event)
|
|||
|
|
|||
|
if (method === 'GET') {
|
|||
|
// 获取用户列表
|
|||
|
const query = getQuery(event)
|
|||
|
const page = parseInt(query.page as string) || 1
|
|||
|
const limit = parseInt(query.limit as string) || 20
|
|||
|
const search = query.search as string
|
|||
|
const role = query.role as string
|
|||
|
const status = query.status as string
|
|||
|
|
|||
|
let queryBuilder = supabase
|
|||
|
.from('profiles')
|
|||
|
.select(`
|
|||
|
id, email, full_name, phone, company, department, role,
|
|||
|
is_active, verification_status, specializations,
|
|||
|
hourly_rate, timezone, created_at, last_login
|
|||
|
`)
|
|||
|
.order('created_at', { ascending: false })
|
|||
|
|
|||
|
// 搜索过滤
|
|||
|
if (search) {
|
|||
|
queryBuilder = queryBuilder.or(`
|
|||
|
full_name.ilike.%${search}%,
|
|||
|
email.ilike.%${search}%,
|
|||
|
company.ilike.%${search}%
|
|||
|
`)
|
|||
|
}
|
|||
|
|
|||
|
// 角色过滤
|
|||
|
if (role) {
|
|||
|
queryBuilder = queryBuilder.eq('role', role)
|
|||
|
}
|
|||
|
|
|||
|
// 状态过滤
|
|||
|
if (status === 'active') {
|
|||
|
queryBuilder = queryBuilder.eq('is_active', true)
|
|||
|
} else if (status === 'inactive') {
|
|||
|
queryBuilder = queryBuilder.eq('is_active', false)
|
|||
|
}
|
|||
|
|
|||
|
// 分页
|
|||
|
const from = (page - 1) * limit
|
|||
|
const to = from + limit - 1
|
|||
|
queryBuilder = queryBuilder.range(from, to)
|
|||
|
|
|||
|
const { data: users, error, count } = await queryBuilder
|
|||
|
|
|||
|
if (error) {
|
|||
|
throw createError({
|
|||
|
statusCode: 500,
|
|||
|
statusMessage: '获取用户列表失败:' + error.message
|
|||
|
})
|
|||
|
}
|
|||
|
|
|||
|
return {
|
|||
|
users,
|
|||
|
pagination: {
|
|||
|
page,
|
|||
|
limit,
|
|||
|
total: count || 0,
|
|||
|
totalPages: Math.ceil((count || 0) / limit)
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
if (method === 'POST') {
|
|||
|
// 创建新用户
|
|||
|
const body = await readBody(event)
|
|||
|
const { email, password, full_name, role, phone, company, department, specializations, hourly_rate, timezone } = body
|
|||
|
|
|||
|
if (!email || !password || !full_name || !role) {
|
|||
|
throw createError({
|
|||
|
statusCode: 400,
|
|||
|
statusMessage: '缺少必要字段:email, password, full_name, role'
|
|||
|
})
|
|||
|
}
|
|||
|
|
|||
|
// 创建认证用户
|
|||
|
const { data: authData, error: authError } = await supabase.auth.admin.createUser({
|
|||
|
email,
|
|||
|
password,
|
|||
|
email_confirm: true
|
|||
|
})
|
|||
|
|
|||
|
if (authError) {
|
|||
|
throw createError({
|
|||
|
statusCode: 400,
|
|||
|
statusMessage: '创建用户失败:' + authError.message
|
|||
|
})
|
|||
|
}
|
|||
|
|
|||
|
// 创建用户资料
|
|||
|
const { data: profileData, error: profileError } = await supabase
|
|||
|
.from('profiles')
|
|||
|
.insert({
|
|||
|
id: authData.user.id,
|
|||
|
email,
|
|||
|
full_name,
|
|||
|
phone,
|
|||
|
company,
|
|||
|
department,
|
|||
|
role,
|
|||
|
specializations: specializations || [],
|
|||
|
hourly_rate,
|
|||
|
timezone: timezone || 'UTC',
|
|||
|
verification_status: 'verified' // 管理员创建的用户自动验证
|
|||
|
})
|
|||
|
.select()
|
|||
|
.single()
|
|||
|
|
|||
|
if (profileError) {
|
|||
|
// 如果创建资料失败,删除已创建的认证用户
|
|||
|
await supabase.auth.admin.deleteUser(authData.user.id)
|
|||
|
throw createError({
|
|||
|
statusCode: 500,
|
|||
|
statusMessage: '创建用户资料失败:' + profileError.message
|
|||
|
})
|
|||
|
}
|
|||
|
|
|||
|
return {
|
|||
|
message: '用户创建成功',
|
|||
|
user: profileData
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
if (method === 'PUT') {
|
|||
|
// 更新用户信息
|
|||
|
const body = await readBody(event)
|
|||
|
const { userId, ...updateData } = body
|
|||
|
|
|||
|
if (!userId) {
|
|||
|
throw createError({
|
|||
|
statusCode: 400,
|
|||
|
statusMessage: '缺少用户ID'
|
|||
|
})
|
|||
|
}
|
|||
|
|
|||
|
// 更新用户资料
|
|||
|
const { data: updatedUser, error } = await supabase
|
|||
|
.from('profiles')
|
|||
|
.update({
|
|||
|
...updateData,
|
|||
|
updated_at: new Date().toISOString()
|
|||
|
})
|
|||
|
.eq('id', userId)
|
|||
|
.select()
|
|||
|
.single()
|
|||
|
|
|||
|
if (error) {
|
|||
|
throw createError({
|
|||
|
statusCode: 500,
|
|||
|
statusMessage: '更新用户失败:' + error.message
|
|||
|
})
|
|||
|
}
|
|||
|
|
|||
|
return {
|
|||
|
message: '用户更新成功',
|
|||
|
user: updatedUser
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
if (method === 'DELETE') {
|
|||
|
// 删除用户
|
|||
|
const body = await readBody(event)
|
|||
|
const { userId } = body
|
|||
|
|
|||
|
if (!userId) {
|
|||
|
throw createError({
|
|||
|
statusCode: 400,
|
|||
|
statusMessage: '缺少用户ID'
|
|||
|
})
|
|||
|
}
|
|||
|
|
|||
|
// 软删除:设置为非活跃状态
|
|||
|
const { error } = await supabase
|
|||
|
.from('profiles')
|
|||
|
.update({
|
|||
|
is_active: false,
|
|||
|
updated_at: new Date().toISOString()
|
|||
|
})
|
|||
|
.eq('id', userId)
|
|||
|
|
|||
|
if (error) {
|
|||
|
throw createError({
|
|||
|
statusCode: 500,
|
|||
|
statusMessage: '删除用户失败:' + error.message
|
|||
|
})
|
|||
|
}
|
|||
|
|
|||
|
return {
|
|||
|
message: '用户删除成功'
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
throw createError({
|
|||
|
statusCode: 405,
|
|||
|
statusMessage: '不支持的请求方法'
|
|||
|
})
|
|||
|
})
|