- Update food, outfits, props, home-decor pages and components - Add permissions page and sidebar updates - Update API client and all API modules (auth, food, dances, etc.) - Add card model migrations for optional fields - Update Django views, serializers, and authentication - Add affinity level migrations and user app updates - Add project documentation Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
101 lines
3.6 KiB
TypeScript
101 lines
3.6 KiB
TypeScript
import type { User, LoginHistory } from "./types"
|
||
import { apiClient } from "./client"
|
||
import type { PaginatedResponse, PaginationParams } from "./client"
|
||
|
||
// 将后端 ParadiseUser 数据映射到前端 User 类型
|
||
function mapBackendUser(u: any): User {
|
||
return {
|
||
id: String(u.id),
|
||
name: u.username || u.email || u.phone_number || "",
|
||
email: u.email || "",
|
||
role: u.is_superuser ? "超级管理员" : u.is_staff ? "管理员" : "普通用户",
|
||
status: u.is_active ? "活跃" : "未激活",
|
||
registeredAt: u.date_joined ? u.date_joined.split("T")[0] : "",
|
||
lastLogin: u.last_login ? u.last_login.split("T")[0] : undefined,
|
||
phone: u.phone_number || undefined,
|
||
address: u.resident_city || undefined,
|
||
avatar: undefined,
|
||
permissions: [],
|
||
loginHistory: [],
|
||
}
|
||
}
|
||
|
||
// 获取用户列表
|
||
export const getUsers = async (params?: PaginationParams): Promise<PaginatedResponse<User>> => {
|
||
const page = params?.page || 1
|
||
const pageSize = params?.pageSize || 10
|
||
const searchParam = params?.search ? `&search=${encodeURIComponent(params.search)}` : ""
|
||
|
||
const response = await apiClient.get(`/user/?page=${page}&page_size=${pageSize}${searchParam}`)
|
||
const data = response.data
|
||
|
||
// 后端直接返回分页数据(DRF 默认格式)
|
||
const results: any[] = data.results || data
|
||
const total = data.count || results.length
|
||
|
||
return {
|
||
items: results.map(mapBackendUser),
|
||
total,
|
||
page,
|
||
pageSize,
|
||
totalPages: Math.ceil(total / pageSize),
|
||
}
|
||
}
|
||
|
||
// 获取单个用户
|
||
export const getUser = async (id: string): Promise<User> => {
|
||
const response = await apiClient.get(`/user/${id}/`)
|
||
return mapBackendUser(response.data)
|
||
}
|
||
|
||
// 创建用户
|
||
export const createUser = async (userData: Partial<User> & { password?: string }): Promise<User> => {
|
||
const payload: any = {
|
||
username: userData.name,
|
||
email: userData.email,
|
||
phone_number: userData.phone,
|
||
password1: userData.password || "changeme123",
|
||
password2: userData.password || "changeme123",
|
||
is_active: userData.status === "活跃",
|
||
is_staff: userData.role === "管理员" || userData.role === "超级管理员",
|
||
}
|
||
const response = await apiClient.post(`/user/`, payload)
|
||
return mapBackendUser(response.data)
|
||
}
|
||
|
||
// 更新用户
|
||
export const updateUser = async (id: string, userData: Partial<User>): Promise<User> => {
|
||
const payload: any = {}
|
||
if (userData.name !== undefined) payload.username = userData.name
|
||
if (userData.email !== undefined) payload.email = userData.email
|
||
if (userData.phone !== undefined) payload.phone_number = userData.phone
|
||
if (userData.address !== undefined) payload.resident_city = userData.address
|
||
if (userData.status !== undefined) payload.is_active = userData.status === "活跃"
|
||
if (userData.role !== undefined) {
|
||
payload.is_staff = userData.role === "管理员" || userData.role === "超级管理员"
|
||
payload.is_superuser = userData.role === "超级管理员"
|
||
}
|
||
|
||
const response = await apiClient.patch(`/user/${id}/`, payload)
|
||
return mapBackendUser(response.data)
|
||
}
|
||
|
||
// 删除用户
|
||
export const deleteUser = async (id: string): Promise<boolean> => {
|
||
await apiClient.delete(`/user/${id}/`)
|
||
return true
|
||
}
|
||
|
||
// 更改用户状态
|
||
export const changeUserStatus = async (id: string, status: User["status"]): Promise<User> => {
|
||
const response = await apiClient.patch(`/user/${id}/`, {
|
||
is_active: status === "活跃",
|
||
})
|
||
return mapBackendUser(response.data)
|
||
}
|
||
|
||
// 获取用户登录历史(后端暂无此接口,返回空数组)
|
||
export const getUserLoginHistory = async (_id: string): Promise<LoginHistory[]> => {
|
||
return []
|
||
}
|