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:
TradeMate Dev
2026-05-20 14:30:50 +08:00
parent f8a23855d2
commit a60aac4638
12 changed files with 689 additions and 67 deletions
+76
View File
@@ -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