Unify frontend config, fix marketing tracking field mismatch, expose customer notes in API
Centralizes all hardcoded page paths, storage keys, external URLs, and branding into a single uni-app/src/config.js. Fixes trackMarketingEffect sending wrong field names (action/content_preview -> event_type/content) that silently dropped tracking data. Adds notes, estimated_value, next_followup_at to Customer response. Removes '翻译' from bottom tab nav (5 tabs now), adds quick translate card on home page. Makes profile page header color consistent with app theme (#1890ff).
This commit is contained in:
@@ -189,6 +189,16 @@ async def get_me(
|
||||
}
|
||||
|
||||
|
||||
class ProfileUpdate(BaseModel):
|
||||
username: str = None
|
||||
email: str = None
|
||||
|
||||
|
||||
class PasswordChange(BaseModel):
|
||||
old_password: str
|
||||
new_password: str
|
||||
|
||||
|
||||
class SettingsUpdate(BaseModel):
|
||||
preferred_translate_provider: str = None
|
||||
reply_tone: str = None
|
||||
@@ -202,6 +212,72 @@ class WeChatLoginRequest(BaseModel):
|
||||
iv: str = ""
|
||||
|
||||
|
||||
@router.put("/me")
|
||||
async def update_me(
|
||||
data: ProfileUpdate,
|
||||
authorization: Optional[str] = Header(None, alias="Authorization"),
|
||||
db: AsyncSession = Depends(get_db),
|
||||
):
|
||||
if not authorization or not authorization.startswith("Bearer "):
|
||||
raise HTTPException(status_code=401, detail="Missing token")
|
||||
|
||||
payload = decode_token(authorization[7:])
|
||||
if not payload:
|
||||
raise HTTPException(status_code=401, detail="Invalid token")
|
||||
|
||||
if payload.get("is_guest"):
|
||||
raise HTTPException(status_code=403, detail="Guests cannot update profile")
|
||||
|
||||
result = await db.execute(select(User).where(User.id == payload["sub"]))
|
||||
user = result.scalar_one_or_none()
|
||||
if not user:
|
||||
raise HTTPException(status_code=404, detail="User not found")
|
||||
|
||||
if data.username is not None:
|
||||
user.username = data.username
|
||||
if data.email is not None:
|
||||
user.email = data.email
|
||||
|
||||
await db.flush()
|
||||
return {
|
||||
"id": str(user.id),
|
||||
"phone": user.phone,
|
||||
"username": user.username,
|
||||
"email": user.email,
|
||||
"tier": user.tier,
|
||||
"role": user.role,
|
||||
}
|
||||
|
||||
|
||||
@router.put("/password")
|
||||
async def change_password(
|
||||
data: PasswordChange,
|
||||
authorization: Optional[str] = Header(None, alias="Authorization"),
|
||||
db: AsyncSession = Depends(get_db),
|
||||
):
|
||||
if not authorization or not authorization.startswith("Bearer "):
|
||||
raise HTTPException(status_code=401, detail="Missing token")
|
||||
|
||||
payload = decode_token(authorization[7:])
|
||||
if not payload:
|
||||
raise HTTPException(status_code=401, detail="Invalid token")
|
||||
|
||||
if payload.get("is_guest"):
|
||||
raise HTTPException(status_code=403, detail="Guests cannot change password")
|
||||
|
||||
result = await db.execute(select(User).where(User.id == payload["sub"]))
|
||||
user = result.scalar_one_or_none()
|
||||
if not user:
|
||||
raise HTTPException(status_code=404, detail="User not found")
|
||||
|
||||
if not verify_password(data.old_password, user.password_hash):
|
||||
raise HTTPException(status_code=400, detail="旧密码不正确")
|
||||
|
||||
user.password_hash = hash_password(data.new_password)
|
||||
await db.flush()
|
||||
return {"message": "密码修改成功"}
|
||||
|
||||
|
||||
@router.get("/wechat/config")
|
||||
async def wechat_config():
|
||||
from app.config import settings
|
||||
|
||||
Reference in New Issue
Block a user