pmc bd95ba470c feat: update admin panel, API modules, and add migrations
- 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>
2026-03-20 13:06:50 +08:00

313 lines
8.3 KiB
TypeScript

import { apiClient } from "./client";
import type {
Food,
UserFood,
FoodStats,
MyFoodStats,
UseFoodRequest,
FoodCategoriesInfo,
FoodUsageLog,
ApiResponse,
PaginatedData
} from "./types";
import type { PaginationParams } from "./client";
/**
* 获取食物列表
* @param params 分页参数
* @returns 食物列表的分页响应
*/
export const getFoods = async (params?: PaginationParams): Promise<ApiResponse<PaginatedData<Food>>> => {
try {
const searchParams = new URLSearchParams();
if (params?.page) searchParams.append('page', params.page.toString());
if (params?.pageSize) searchParams.append('page_size', params.pageSize.toString());
if (params?.search) searchParams.append('search', params.search);
const response = await apiClient.get(`/food/foods/?${searchParams.toString()}`);
if (!response.data.success) {
throw new Error(response.data.message || '获取食物列表失败');
}
return response.data;
} catch (error) {
console.error("获取食物列表失败:", error);
throw error;
}
};
/**
* 获取食物详情
* @param id 食物ID
* @returns 食物详情
*/
export const getFood = async (id: string): Promise<ApiResponse<Food>> => {
try {
const response = await apiClient.get(`/food/foods/${id}/`);
if (!response.data.success) {
throw new Error(response.data.message || '获取食物详情失败');
}
return response.data;
} catch (error) {
console.error("获取食物详情失败:", error);
throw error;
}
};
/**
* 获取用户的食物
* @param params 分页参数
* @returns 用户食物列表的分页响应
*/
export const getUserFoods = async (params?: PaginationParams): Promise<ApiResponse<PaginatedData<UserFood>>> => {
try {
const searchParams = new URLSearchParams();
if (params?.page) searchParams.append('page', params.page.toString());
if (params?.pageSize) searchParams.append('page_size', params.pageSize.toString());
if (params?.search) searchParams.append('search', params.search);
const response = await apiClient.get(`/food/user-foods/?${searchParams.toString()}`);
if (!response.data.success) {
throw new Error(response.data.message || '获取用户食物失败');
}
return response.data;
} catch (error) {
console.error("获取用户食物失败:", error);
throw error;
}
};
/**
* 使用食物
* @param useFoodData 使用食物的数据
* @returns 使用结果
*/
export const useFood = async (useFoodData: UseFoodRequest): Promise<ApiResponse<{ message: string }>> => {
try {
const response = await apiClient.post('/food/use-food/', {
food_id: useFoodData.foodId,
quantity: useFoodData.quantity || 1,
});
if (!response.data.success) {
throw new Error(response.data.message || '使用食物失败');
}
return response.data;
} catch (error) {
console.error("使用食物失败:", error);
throw error;
}
};
/**
* 获取我的食物统计
* @returns 我的食物统计
*/
export const getMyFoodStats = async (): Promise<ApiResponse<MyFoodStats>> => {
try {
const response = await apiClient.get('/food/my-foods/');
if (!response.data.success) {
throw new Error(response.data.message || '获取我的食物统计失败');
}
return response.data;
} catch (error) {
console.error("获取我的食物统计失败:", error);
throw error;
}
};
/**
* 获取系统食物统计
* @returns 系统食物统计
*/
export const getFoodStats = async (): Promise<ApiResponse<FoodStats>> => {
try {
const response = await apiClient.get('/food/food-stats/');
if (!response.data.success) {
throw new Error(response.data.message || '获取系统统计失败');
}
return response.data;
} catch (error) {
console.error("获取系统统计失败:", error);
throw error;
}
};
/**
* 创建新食物
* @param foodData 食物数据
* @returns 创建的食物
*/
export const createFood = async (foodData: Partial<Food>): Promise<ApiResponse<Food>> => {
try {
const response = await apiClient.post('/food/foods/', foodData);
if (!response.data.success) {
throw new Error(response.data.message || '创建食物失败');
}
return response.data;
} catch (error) {
console.error("创建食物失败:", error);
throw error;
}
};
/**
* 部分更新食物 (PATCH)
* @param id 食物ID
* @param foodData 要更新的食物数据
* @returns 更新后的食物
*/
export const updateFood = async (id: string, foodData: Partial<Food>): Promise<ApiResponse<Food>> => {
try {
const response = await apiClient.patch(`/food/foods/${id}/`, foodData);
if (!response.data.success) {
throw new Error(response.data.message || '更新食物失败');
}
return response.data;
} catch (error) {
console.error("更新食物失败:", error);
throw error;
}
};
/**
* 完整更新食物 (PUT)
* @param id 食物ID
* @param foodData 完整的食物数据
* @returns 更新后的食物
*/
export const replaceFood = async (id: string, foodData: Omit<Food, 'id' | 'created_at' | 'updated_at'>): Promise<ApiResponse<Food>> => {
try {
const response = await apiClient.put(`/food/foods/${id}/`, foodData);
if (!response.data.success) {
throw new Error(response.data.message || '完整更新食物失败');
}
return response.data;
} catch (error) {
console.error("完整更新食物失败:", error);
throw error;
}
};
/**
* 发布食物
* @param id 食物ID
* @returns 发布结果
*/
export const publishFood = async (id: string): Promise<ApiResponse<{ message: string }>> => {
try {
const response = await apiClient.post(`/food/foods/${id}/publish/`);
if (!response.data.success) {
throw new Error(response.data.message || '发布食物失败');
}
return response.data;
} catch (error) {
console.error("发布食物失败:", error);
throw error;
}
};
/**
* 归档食物
* @param id 食物ID
* @returns 归档结果
*/
export const archiveFood = async (id: string): Promise<ApiResponse<{ message: string }>> => {
try {
const response = await apiClient.post(`/food/foods/${id}/archive/`);
if (!response.data.success) {
throw new Error(response.data.message || '归档食物失败');
}
return response.data;
} catch (error) {
console.error("归档食物失败:", error);
throw error;
}
};
/**
* 删除食物
* @param id 食物ID
* @returns 删除结果
*/
export const deleteFood = async (id: string): Promise<ApiResponse<{ message: string }>> => {
try {
const response = await apiClient.delete(`/food/foods/${id}/`);
if (!response.data.success) {
throw new Error(response.data.message || '删除食物失败');
}
return response.data;
} catch (error) {
console.error("删除食物失败:", error);
throw error;
}
};
/**
* 获取食物分类和稀有度信息
* @returns 食物分类和稀有度信息
*/
export const getFoodCategories = async (): Promise<ApiResponse<FoodCategoriesInfo>> => {
try {
const response = await apiClient.get('/food/foods/categories/');
if (!response.data.success) {
throw new Error(response.data.message || '获取食物分类信息失败');
}
return response.data;
} catch (error) {
console.error("获取食物分类信息失败:", error);
throw error;
}
};
/**
* 获取用户的食物使用记录
* @param params 分页参数
* @returns 食物使用记录的分页响应
*/
export const getFoodUsageLogs = async (params?: PaginationParams): Promise<ApiResponse<PaginatedData<FoodUsageLog>>> => {
try {
const searchParams = new URLSearchParams();
if (params?.page) searchParams.append('page', params.page.toString());
if (params?.pageSize) searchParams.append('page_size', params.pageSize.toString());
if (params?.search) searchParams.append('search', params.search);
const response = await apiClient.get(`/food/usage-logs/?${searchParams.toString()}`);
if (!response.data.success) {
throw new Error(response.data.message || '获取食物使用记录失败');
}
return response.data;
} catch (error) {
console.error("获取食物使用记录失败:", error);
throw error;
}
};