|
|
@@ -1,4 +1,4 @@
|
|
|
-import React, { useState, useEffect } from 'react';
|
|
|
+import React, { useState } from 'react';
|
|
|
import { useAuth } from '../hooks/AuthProvider';
|
|
|
import { useNavigate } from 'react-router-dom';
|
|
|
import { silverUserProfileClient, userClient } from '@/client/api';
|
|
|
@@ -7,6 +7,7 @@ import { zodResolver } from '@hookform/resolvers/zod';
|
|
|
import { z } from 'zod';
|
|
|
import { toast } from 'sonner';
|
|
|
import { InferRequestType, InferResponseType } from 'hono/client';
|
|
|
+import { useQuery, useMutation, useQueryClient } from '@tanstack/react-query';
|
|
|
|
|
|
// 导入 shadcn 组件
|
|
|
import { Button } from '@/client/components/ui/button';
|
|
|
@@ -46,9 +47,7 @@ type ProfileFormData = z.infer<typeof profileFormSchema>;
|
|
|
const ProfileEditPage: React.FC = () => {
|
|
|
const { user } = useAuth();
|
|
|
const navigate = useNavigate();
|
|
|
- const [loading, setLoading] = useState(false);
|
|
|
- const [profile, setProfile] = useState<ProfileResponse | null>(null);
|
|
|
- const [isLoading, setIsLoading] = useState(true);
|
|
|
+ const queryClient = useQueryClient();
|
|
|
const [avatarFileId, setAvatarFileId] = useState<number | null>(null);
|
|
|
|
|
|
// 初始化表单
|
|
|
@@ -68,64 +67,101 @@ const ProfileEditPage: React.FC = () => {
|
|
|
},
|
|
|
});
|
|
|
|
|
|
- useEffect(() => {
|
|
|
- if (user) {
|
|
|
- loadProfile();
|
|
|
- }
|
|
|
- }, [user]);
|
|
|
-
|
|
|
- const loadProfile = async () => {
|
|
|
- if (!user) return;
|
|
|
-
|
|
|
- try {
|
|
|
- setIsLoading(true);
|
|
|
+ // 使用 React Query 获取用户档案数据
|
|
|
+ const { data: profileData, isLoading: isLoadingProfile, error: profileError } = useQuery({
|
|
|
+ queryKey: ['userProfile', user?.id],
|
|
|
+ queryFn: async () => {
|
|
|
+ if (!user) throw new Error('用户未登录');
|
|
|
+
|
|
|
const response = await silverUserProfileClient.$get({
|
|
|
query: { filters: JSON.stringify({ userId: user.id }) }
|
|
|
});
|
|
|
|
|
|
- if (response.status === 200) {
|
|
|
- const data = await response.json();
|
|
|
- if (data.data && data.data.length > 0) {
|
|
|
- const profileData = data.data[0];
|
|
|
- setProfile(profileData);
|
|
|
- setAvatarFileId(profileData.avatarFileId || null);
|
|
|
-
|
|
|
- // 填充表单数据
|
|
|
- form.reset({
|
|
|
- username: user.username || '',
|
|
|
- email: user.email || '',
|
|
|
- phone: profileData.phone || user.phone || '',
|
|
|
- realName: profileData.realName || '',
|
|
|
- age: profileData.age || 18,
|
|
|
- gender: profileData.gender || 1,
|
|
|
- organization: profileData.organization || '',
|
|
|
- personalIntro: profileData.personalIntro || '',
|
|
|
- personalSkills: profileData.personalSkills || '',
|
|
|
- personalExperience: profileData.personalExperience || '',
|
|
|
- });
|
|
|
- } else {
|
|
|
- // 新用户,使用现有用户信息填充
|
|
|
- form.reset({
|
|
|
- username: user.username || '',
|
|
|
- email: user.email || '',
|
|
|
- phone: user.phone || '',
|
|
|
- realName: '',
|
|
|
- age: 18,
|
|
|
- gender: 1,
|
|
|
- organization: '',
|
|
|
- personalIntro: '',
|
|
|
- personalSkills: '',
|
|
|
- personalExperience: '',
|
|
|
- });
|
|
|
+ if (response.status !== 200) {
|
|
|
+ throw new Error('获取档案失败');
|
|
|
+ }
|
|
|
+
|
|
|
+ const data = await response.json();
|
|
|
+ return data.data?.[0] || null;
|
|
|
+ },
|
|
|
+ enabled: !!user,
|
|
|
+ });
|
|
|
+
|
|
|
+ // 使用 React Query 更新用户信息
|
|
|
+ const updateUserMutation = useMutation({
|
|
|
+ mutationFn: async (data: UpdateUserRequest) => {
|
|
|
+ if (!user) throw new Error('用户未登录');
|
|
|
+
|
|
|
+ const response = await userClient[':id'].$put({
|
|
|
+ param: { id: user.id },
|
|
|
+ json: data,
|
|
|
+ });
|
|
|
+
|
|
|
+ if (response.status !== 200) {
|
|
|
+ throw new Error('更新用户信息失败');
|
|
|
+ }
|
|
|
+
|
|
|
+ return response.json();
|
|
|
+ },
|
|
|
+ onSuccess: () => {
|
|
|
+ queryClient.invalidateQueries({ queryKey: ['userProfile', user?.id] });
|
|
|
+ },
|
|
|
+ });
|
|
|
+
|
|
|
+ // 使用 React Query 创建/更新档案
|
|
|
+ const updateProfileMutation = useMutation({
|
|
|
+ mutationFn: async (data: CreateProfileRequest | UpdateProfileRequest) => {
|
|
|
+ if (!user) throw new Error('用户未登录');
|
|
|
+
|
|
|
+ const isUpdate = profileData?.id;
|
|
|
+
|
|
|
+ if (isUpdate) {
|
|
|
+ const response = await silverUserProfileClient[':id'].$put({
|
|
|
+ param: { id: profileData.id },
|
|
|
+ json: data as UpdateProfileRequest,
|
|
|
+ });
|
|
|
+
|
|
|
+ if (response.status !== 200) {
|
|
|
+ throw new Error('更新档案失败');
|
|
|
}
|
|
|
+
|
|
|
+ return response.json();
|
|
|
+ } else {
|
|
|
+ const response = await silverUserProfileClient.$post({
|
|
|
+ json: data as CreateProfileRequest,
|
|
|
+ });
|
|
|
+
|
|
|
+ if (response.status !== 201) {
|
|
|
+ throw new Error('创建档案失败');
|
|
|
+ }
|
|
|
+
|
|
|
+ return response.json();
|
|
|
}
|
|
|
- } catch (error) {
|
|
|
- console.error('加载个人档案失败:', error);
|
|
|
- toast.error('加载个人档案失败');
|
|
|
- } finally {
|
|
|
- setIsLoading(false);
|
|
|
+ },
|
|
|
+ onSuccess: () => {
|
|
|
+ queryClient.invalidateQueries({ queryKey: ['userProfile', user?.id] });
|
|
|
+ },
|
|
|
+ });
|
|
|
+
|
|
|
+ // 根据获取的数据填充表单
|
|
|
+ React.useEffect(() => {
|
|
|
+ if (user && profileData !== undefined) {
|
|
|
+ setAvatarFileId(profileData?.avatarFileId || null);
|
|
|
+
|
|
|
+ form.reset({
|
|
|
+ username: user.username || '',
|
|
|
+ email: user.email || '',
|
|
|
+ phone: profileData?.phone || user.phone || '',
|
|
|
+ realName: profileData?.realName || '',
|
|
|
+ age: profileData?.age || 18,
|
|
|
+ gender: profileData?.gender || 1,
|
|
|
+ organization: profileData?.organization || '',
|
|
|
+ personalIntro: profileData?.personalIntro || '',
|
|
|
+ personalSkills: profileData?.personalSkills || '',
|
|
|
+ personalExperience: profileData?.personalExperience || '',
|
|
|
+ });
|
|
|
}
|
|
|
- };
|
|
|
+ }, [user, profileData, form]);
|
|
|
|
|
|
const handleAvatarChange = (fileId: number) => {
|
|
|
setAvatarFileId(fileId);
|
|
|
@@ -134,7 +170,6 @@ const ProfileEditPage: React.FC = () => {
|
|
|
const onSubmit = async (data: ProfileFormData) => {
|
|
|
if (!user) return;
|
|
|
|
|
|
- setLoading(true);
|
|
|
try {
|
|
|
// 更新用户信息
|
|
|
const userUpdateData: UpdateUserRequest = {
|
|
|
@@ -143,53 +178,30 @@ const ProfileEditPage: React.FC = () => {
|
|
|
phone: data.phone,
|
|
|
};
|
|
|
|
|
|
- const userUpdateResponse = await userClient[':id'].$put({
|
|
|
- param: { id: user.id },
|
|
|
- json: userUpdateData,
|
|
|
- });
|
|
|
+ await updateUserMutation.mutateAsync(userUpdateData);
|
|
|
|
|
|
- if (userUpdateResponse.status === 200) {
|
|
|
- // 更新银龄档案
|
|
|
- const profileData: CreateProfileRequest | UpdateProfileRequest = {
|
|
|
- userId: user.id,
|
|
|
- realName: data.realName,
|
|
|
- age: data.age,
|
|
|
- gender: data.gender as 1 | 2 | 3,
|
|
|
- phone: data.phone,
|
|
|
- email: data.email,
|
|
|
- avatarFileId: avatarFileId || undefined,
|
|
|
- organization: data.organization,
|
|
|
- personalIntro: data.personalIntro,
|
|
|
- personalSkills: data.personalSkills,
|
|
|
- personalExperience: data.personalExperience,
|
|
|
- };
|
|
|
-
|
|
|
- let response;
|
|
|
- if (profile?.id) {
|
|
|
- response = await silverUserProfileClient[':id'].$put({
|
|
|
- param: { id: profile.id },
|
|
|
- json: profileData as UpdateProfileRequest,
|
|
|
- });
|
|
|
- } else {
|
|
|
- response = await silverUserProfileClient.$post({
|
|
|
- json: profileData as CreateProfileRequest,
|
|
|
- });
|
|
|
- }
|
|
|
+ // 更新银龄档案
|
|
|
+ const profileData: CreateProfileRequest | UpdateProfileRequest = {
|
|
|
+ userId: user.id,
|
|
|
+ realName: data.realName,
|
|
|
+ age: data.age,
|
|
|
+ gender: data.gender as 1 | 2 | 3,
|
|
|
+ phone: data.phone,
|
|
|
+ email: data.email,
|
|
|
+ avatarFileId: avatarFileId || undefined,
|
|
|
+ organization: data.organization,
|
|
|
+ personalIntro: data.personalIntro,
|
|
|
+ personalSkills: data.personalSkills,
|
|
|
+ personalExperience: data.personalExperience,
|
|
|
+ };
|
|
|
|
|
|
- if (response.status === 200 || response.status === 201) {
|
|
|
- toast.success('个人信息更新成功');
|
|
|
- navigate('/profile');
|
|
|
- } else {
|
|
|
- throw new Error('更新个人档案失败');
|
|
|
- }
|
|
|
- } else {
|
|
|
- throw new Error('更新用户信息失败');
|
|
|
- }
|
|
|
+ await updateProfileMutation.mutateAsync(profileData);
|
|
|
+
|
|
|
+ toast.success('个人信息更新成功');
|
|
|
+ navigate('/profile');
|
|
|
} catch (error) {
|
|
|
console.error('更新失败:', error);
|
|
|
toast.error('更新失败,请重试');
|
|
|
- } finally {
|
|
|
- setLoading(false);
|
|
|
}
|
|
|
};
|
|
|
|
|
|
@@ -210,7 +222,7 @@ const ProfileEditPage: React.FC = () => {
|
|
|
);
|
|
|
}
|
|
|
|
|
|
- if (isLoading) {
|
|
|
+ if (isLoadingProfile) {
|
|
|
return (
|
|
|
<div className="min-h-screen bg-gray-50">
|
|
|
<div className="bg-white border-b">
|
|
|
@@ -262,7 +274,7 @@ const ProfileEditPage: React.FC = () => {
|
|
|
<CardContent>
|
|
|
<div className="flex items-center space-x-4">
|
|
|
<AvatarUpload
|
|
|
- currentAvatar={avatarFileId ? profile?.avatarFile?.fullUrl : ''}
|
|
|
+ currentAvatar={avatarFileId ? profileData?.avatarFile?.fullUrl : ''}
|
|
|
size={80}
|
|
|
onUploadSuccess={handleAvatarChange}
|
|
|
/>
|