diff --git a/backend/app/routers/auth.py b/backend/app/routers/auth.py
index fa4fdd1..f77cf67 100644
--- a/backend/app/routers/auth.py
+++ b/backend/app/routers/auth.py
@@ -1,9 +1,9 @@
# 认证路由 - 使用字段编码
-from fastapi import APIRouter, Depends, HTTPException, status
+from fastapi import APIRouter, Depends, HTTPException, status, Body
from fastapi.security import OAuth2PasswordRequestForm
from sqlalchemy.orm import Session
from app.core.database import get_db
-from app.core.auth import verify_password, create_access_token, get_password_hash
+from app.core.auth import verify_password, create_access_token, get_password_hash, get_current_user
from app.models.models import User
from app.schemas.schemas import Token, UserCreate, UserResponse
@@ -94,3 +94,27 @@ def get_current_user_info(
status_code=status.HTTP_501_NOT_IMPLEMENTED,
detail="请使用正确的依赖注入"
)
+
+
+@router.post("/change-password")
+def change_password(
+ old_password: str = Body(...),
+ new_password: str = Body(...),
+ current_user: User = Depends(get_current_user),
+ db: Session = Depends(get_db)
+):
+ """修改当前用户密码"""
+ from app.core.auth import verify_password, get_password_hash
+
+ # 验证旧密码
+ if not verify_password(old_password, current_user.password):
+ raise HTTPException(
+ status_code=status.HTTP_400_BAD_REQUEST,
+ detail="当前密码错误"
+ )
+
+ # 更新密码
+ current_user.password = get_password_hash(new_password)
+ db.commit()
+
+ return {"message": "密码修改成功"}
diff --git a/config/VERSION b/config/VERSION
index 0b9bd91..2da7100 100644
--- a/config/VERSION
+++ b/config/VERSION
@@ -2,7 +2,7 @@
# Version Configuration for Zodiac Collection Management System
# 当前版本号 (语义化版本:主版本。次版本.修订版)
-VERSION=1.0.7
+VERSION=1.0.8
# 版本代号 (可选)
VERSION_CODENAME="新生"
diff --git a/frontend/src/App.jsx b/frontend/src/App.jsx
index c0fc23a..375b78d 100644
--- a/frontend/src/App.jsx
+++ b/frontend/src/App.jsx
@@ -1,5 +1,6 @@
import React, { useState, useEffect } from 'react'
import Home from './pages/Home'
+import Settings from './pages/Settings'
import List from './pages/List'
import Add from './pages/Add'
import Stats from './pages/Stats'
@@ -31,6 +32,7 @@ export default function App() {
if (basePath === '/list') return
if (basePath === '/add') return
if (basePath === '/login') return
+ if (basePath === '/settings') return
if (basePath === '/admin') return
if (basePath.startsWith('/edit')) return
if (basePath.startsWith('/detail')) return
diff --git a/frontend/src/pages/Settings.jsx b/frontend/src/pages/Settings.jsx
new file mode 100644
index 0000000..f9f0bd9
--- /dev/null
+++ b/frontend/src/pages/Settings.jsx
@@ -0,0 +1,268 @@
+import React, { useState, useEffect } from 'react'
+import { useNavigate } from 'react-router-dom'
+
+export default function Settings() {
+ const [loading, setLoading] = useState(true)
+ const [saving, setSaving] = useState(false)
+ const [error, setError] = useState('')
+ const [success, setSuccess] = useState('')
+
+ const [form, setForm] = useState({
+ username: '',
+ email: '',
+ phone: '',
+ bio: ''
+ })
+
+ const [passwordForm, setPasswordForm] = useState({
+ oldPassword: '',
+ newPassword: '',
+ confirmPassword: ''
+ })
+
+ const navigate = useNavigate()
+ const token = localStorage.getItem('token')
+
+ useEffect(() => {
+ fetchUserInfo()
+ }, [])
+
+ const fetchUserInfo = async () => {
+ try {
+ const res = await fetch('/api/users/me', {
+ headers: { 'Authorization': 'Bearer ' + token }
+ })
+ if (res.ok) {
+ const data = await res.json()
+ setForm({
+ username: data.username || '',
+ email: data.email || '',
+ phone: data.phone || '',
+ bio: data.bio || ''
+ })
+ }
+ } catch (e) {
+ setError('获取用户信息失败')
+ } finally {
+ setLoading(false)
+ }
+ }
+
+ const handleSubmit = async (e) => {
+ e.preventDefault()
+ setError('')
+ setSuccess('')
+ setSaving(true)
+
+ try {
+ const res = await fetch('/api/users/me', {
+ method: 'PUT',
+ headers: {
+ 'Authorization': 'Bearer ' + token,
+ 'Content-Type': 'application/json'
+ },
+ body: JSON.stringify(form)
+ })
+
+ if (res.ok) {
+ setSuccess('保存成功!')
+ // 更新本地存储的用户信息
+ const userStr = localStorage.getItem('user')
+ if (userStr) {
+ const user = JSON.parse(userStr)
+ user.username = form.username
+ localStorage.setItem('user', JSON.stringify(user))
+ }
+ } else {
+ const data = await res.json()
+ setError(data.error?.message || '保存失败')
+ }
+ } catch (e) {
+ setError('保存失败,请重试')
+ } finally {
+ setSaving(false)
+ }
+ }
+
+ const handlePasswordChange = async (e) => {
+ e.preventDefault()
+ setError('')
+ setSuccess('')
+
+ if (passwordForm.newPassword !== passwordForm.confirmPassword) {
+ setError('两次输入的密码不一致')
+ return
+ }
+
+ if (passwordForm.newPassword.length < 6) {
+ setError('密码长度至少6位')
+ return
+ }
+
+ setSaving(true)
+
+ try {
+ const res = await fetch('/api/auth/change-password', {
+ method: 'POST',
+ headers: {
+ 'Authorization': 'Bearer ' + token,
+ 'Content-Type': 'application/json'
+ },
+ body: JSON.stringify({
+ old_password: passwordForm.oldPassword,
+ new_password: passwordForm.newPassword
+ })
+ })
+
+ if (res.ok) {
+ setSuccess('密码修改成功!')
+ setPasswordForm({ oldPassword: '', newPassword: '', confirmPassword: '' })
+ } else {
+ const data = await res.json()
+ setError(data.error?.message || '密码修改失败')
+ }
+ } catch (e) {
+ setError('密码修改失败,请重试')
+ } finally {
+ setSaving(false)
+ }
+ }
+
+ if (loading) {
+ return (
+
+ )
+ }
+
+ return (
+
+ {/* 顶部导航 */}
+
+
navigate('/')} style={{ cursor: 'pointer', fontSize: '20px' }}>←
+
个人设置
+
+
+ {error &&
{error}
}
+ {success &&
{success}
}
+
+ {/* 基本信息 */}
+
+
+ {/* 修改密码 */}
+
+
修改密码
+
+
+
+
+ {/* 退出登录 */}
+
+
+
+
+ )
+}