pages_profile.tsx 4.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132
  1. import React from 'react'
  2. import { useNavigate } from 'react-router'
  3. import { useForm } from 'react-hook-form'
  4. import { UserAPI } from './api.ts'
  5. import type { User } from '../share/types.ts'
  6. export default function ProfilePage() {
  7. const navigate = useNavigate()
  8. const { register, handleSubmit, formState: { errors }, setValue } = useForm<Omit<User, 'id' | 'role' | 'avatar'> & { password?: string }>()
  9. const [loading, setLoading] = React.useState(false)
  10. const [user, setUser] = React.useState<User | null>(null)
  11. // 获取当前用户信息
  12. React.useEffect(() => {
  13. const fetchUser = async () => {
  14. try {
  15. const res = await UserAPI.getUsers({ limit: 1 })
  16. if (res.data?.length > 0) {
  17. const userData = res.data[0]
  18. setUser(userData)
  19. setValue('username', userData.username)
  20. setValue('nickname', userData.nickname)
  21. setValue('email', userData.email)
  22. setValue('phone', userData.phone)
  23. }
  24. } catch (error) {
  25. console.error('获取用户信息失败:', error)
  26. }
  27. }
  28. fetchUser()
  29. }, [setValue])
  30. // 提交表单更新用户信息
  31. const onSubmit = async (data: User) => {
  32. try {
  33. setLoading(true)
  34. if (!user?.id) return
  35. const updatedUser = await UserAPI.updateUser(user.id, {
  36. nickname: data.nickname,
  37. email: data.email,
  38. phone: data.phone,
  39. ...(data.password ? { password: data.password } : {})
  40. })
  41. setUser(updatedUser.data)
  42. alert('更新成功')
  43. } catch (error) {
  44. console.error('更新失败:', error)
  45. alert('更新失败')
  46. } finally {
  47. setLoading(false)
  48. }
  49. }
  50. return (
  51. <div className="p-4 max-w-md mx-auto">
  52. <h1 className="text-2xl font-bold mb-6 text-gray-800">个人信息</h1>
  53. <form onSubmit={handleSubmit(onSubmit)} className="space-y-4">
  54. <div>
  55. <label className="block text-sm font-medium text-gray-700 mb-1">用户名</label>
  56. <input
  57. {...register('username')}
  58. disabled
  59. className="w-full px-3 py-2 border border-gray-300 rounded-md shadow-sm focus:outline-none focus:ring-blue-500 focus:border-blue-500 bg-gray-100"
  60. />
  61. </div>
  62. <div>
  63. <label className="block text-sm font-medium text-gray-700 mb-1">昵称</label>
  64. <input
  65. {...register('nickname', { required: '请输入昵称' })}
  66. className="w-full px-3 py-2 border border-gray-300 rounded-md shadow-sm focus:outline-none focus:ring-blue-500 focus:border-blue-500"
  67. />
  68. {errors.nickname && <p className="mt-1 text-sm text-red-600">{errors.nickname.message}</p>}
  69. </div>
  70. <div>
  71. <label className="block text-sm font-medium text-gray-700 mb-1">邮箱</label>
  72. <input
  73. {...register('email', {
  74. required: '请输入邮箱',
  75. pattern: {
  76. value: /^[A-Z0-9._%+-]+@[A-Z0-9.-]+\.[A-Z]{2,}$/i,
  77. message: '请输入有效的邮箱地址'
  78. }
  79. })}
  80. type="email"
  81. className="w-full px-3 py-2 border border-gray-300 rounded-md shadow-sm focus:outline-none focus:ring-blue-500 focus:border-blue-500"
  82. />
  83. {errors.email && <p className="mt-1 text-sm text-red-600">{errors.email.message}</p>}
  84. </div>
  85. <div>
  86. <label className="block text-sm font-medium text-gray-700 mb-1">手机号</label>
  87. <input
  88. {...register('phone')}
  89. className="w-full px-3 py-2 border border-gray-300 rounded-md shadow-sm focus:outline-none focus:ring-blue-500 focus:border-blue-500"
  90. />
  91. </div>
  92. <div>
  93. <label className="block text-sm font-medium text-gray-700 mb-1">新密码</label>
  94. <input
  95. {...register('password')}
  96. type="password"
  97. placeholder="留空则不修改密码"
  98. className="w-full px-3 py-2 border border-gray-300 rounded-md shadow-sm focus:outline-none focus:ring-blue-500 focus:border-blue-500"
  99. />
  100. </div>
  101. <div className="flex space-x-3 pt-4">
  102. <button
  103. type="submit"
  104. disabled={loading}
  105. className="px-4 py-2 bg-blue-600 text-white rounded-md hover:bg-blue-700 focus:outline-none focus:ring-2 focus:ring-blue-500 focus:ring-offset-2 disabled:opacity-50"
  106. >
  107. {loading ? '保存中...' : '保存'}
  108. </button>
  109. <button
  110. type="button"
  111. onClick={() => navigate(-1)}
  112. className="px-4 py-2 bg-gray-200 text-gray-800 rounded-md hover:bg-gray-300 focus:outline-none focus:ring-2 focus:ring-gray-500 focus:ring-offset-2"
  113. >
  114. 返回
  115. </button>
  116. </div>
  117. </form>
  118. </div>
  119. )
  120. }