触发条件视图 — 设置页(SettingsPage)


页面:SettingsPage


路由/settings


数据来源:直接调用 API,不走 DataContext(个人资料除外,由 AuthContext 注入)


---


页面进入时


> SettingsPage 在加载时不主动拉取数据,而是等用户点击具体操作时触发 API。


用户信息加载时机:通过 AuthContext 注入(全局已登录状态),由 AuthProvider 初始化时通过 GET /api/auth/me 加载。


---


查看个人资料(读取 AuthContext)


说明:当前登录用户的个人信息来自 AuthContext,由 GET /api/auth/me(应用启动时已调用)提供。


AuthContext 暴露的字段


{
  "user": {
    "id": "string",
    "phone": "string",
    "nickname": "string",
    "email": "string | null",
    "avatar_url": "string",
    "prefer_green_expense": 0 | 1,
    "is_guest": 0 | 1,
    "has_onboarded": 0 | 1,
    "role": "user | admin | developer",
    "created_at": "ISO8601"
  }
}

---


修改昵称(输入新昵称 → 点击保存)


触发 API


PUT /api/auth/me/profile

请求


{
  "nickname": "新昵称"
}

约束

  • nickname 至少 2 字符
  • phone / email 不可修改(传了也会被后端拒绝)

  • 后端处理

    1. 校验 nickname 长度

    2. UPDATE users SET nickname = :nickname, updated_at = NOW() WHERE id = :userId


    DB 表users


    后续动作:更新成功后刷新 AuthContext 中的 user 对象


    ---


    修改头像(选择图片 → 点击保存)


    触发 API


    PUT /api/auth/me/profile

    请求

    
    {
      "avatar_url": "https://example.com/avatar.jpg"
    }
    

    说明

  • 头像 URL 可以是任意公网可访问图片地址
  • 后端无图片上传接口,头像 URL 由前端自行上传到第三方图床后传入

  • DB 表users


    后续动作:成功后刷新 AuthContext


    ---


    切换「支出绿色显示」开关


    触发 API


    PUT /api/auth/me/profile

    请求

    
    {
      "prefer_green_expense": true
    }
    

    说明

  • prefer_green_expense = 1 → 支出金额显示为绿色
  • prefer_green_expense = 0 → 支出金额显示为红色(默认)

  • DB 表users


    后续动作:成功后刷新 AuthContext,HomePage/BillPage 的交易金额颜色同步更新


    ---


    修改密码(设置页 → 密码修改)


    > 注:需正式账号(is_guest=0),游客无密码字段


    说明:设置页如有密码修改入口,对应的是注册流程中的 POST /auth/upgrade-guest(游客转正带密码)或忘记密码重置流程,与 SettingsPage 本身无直接关联。


    ---


    AI Keys 管理(AI 配置卡片)


    说明:AI Keys 管理是 SettingsPage 的核心功能之一,允许用户配置、管理和共享 AI API Keys。


    页面加载时


    触发 APIfetchKeys(),并行请求):


    1. GET /api/apikeys/user

    说明:获取当前用户在指定账单下配置的个人 Key 列表

    Query 参数billId(当前账单 ID)

    响应

    
    {
      "keys": [
        {
          "id": "string",
          "provider": "openai | claude | gemini | ...",
          "model": "gpt-4o | claude-3-5-sonnet | gemini-1.5-pro | ...",
          "api_key_encrypted": "HIDDEN | sk-...",
          "is_shared": 1,
          "priority": 100
        }
      ]
    }
    

    2. GET /api/apikeys/suggestions

    说明:获取可从其他账单导入的 Key 建议

    Query 参数currentBillId(当前账单 ID,排除已配置项)

    响应

    
    {
      "suggestions": [
        {
          "id": "string",
          "name": "工作账单 (其他)",
          "key_count": 1,
          "details": [{ "provider": "gemini", "model": "gemini-1.5-pro" }]
        }
      ]
    }
    

    关联 DB 表api_keysbills


    ---


    点击「添加配置」→ 填写表单 → 点击「保存」


    前置条件:先选择 Provider 和 Model,再填写 API Key


    触发 API(保存前先验证):


    1. POST /api/apikeys/verify/user(验证连通性)

    说明:仅当填写了 api_key 时才发送验证请求

    请求

    
    {
      "provider": "openai",
      "api_key": "sk-...",
      "model": "gpt-4o",
      "billId": "B8K2L4P9Q0"
    }
    

    后端处理:用该 Key 实际发起 API 调用测试连通性

    用途:让用户在保存前确认 Key 有效


    2. PUT /api/apikeys/user(保存/更新)

    请求

    
    {
      "provider": "openai",
      "api_key": "sk-...",
      "model": "gpt-4o",
      "is_shared": 1,
      "priority": 100,
      "billId": "B8K2L4P9Q0"
    }
    

    说明

  • api_key 留空则保留原值(不清空)
  • is_shared = 1 → 允许账单成员使用
  • priority 越小越优先

  • 关联 DB 表api_keys


    后续动作

    1. 调用 fetchKeys() 刷新 Key 列表

    2. 触发 ai-keys-updated 事件,通知 ChatBar 等组件刷新


    ---


    点击「共享开关」→ 切换共享状态


    触发 API


    PATCH /api/apikeys/user/share

    请求

    
    {
      "billId": "B8K2L4P9Q0",
      "provider": "openai",
      "model": "gpt-4o",
      "is_shared": 1
    }
    

    说明:切换 Key 的共享状态

    向后兼容:若后端返回 404,则 fallback 到 PUT /api/apikeys/user 全量更新


    关联 DB 表api_keys


    ---


    点击「删除」→ 确认删除


    触发 API


    DELETE /api/apikeys/user/:provider

    请求:Query 参数 model + billId

    
    DELETE /api/apikeys/user/openai?model=gpt-4o&billId=B8K2L4P9Q0
    

    说明:删除用户在指定账单下的某个 Key 配置


    关联 DB 表api_keys


    后续动作

    1. 调用 fetchKeys() 刷新列表

    2. 触发 ai-keys-updated 事件


    ---


    点击「导入」→ 从其他账单同步配置


    触发 API


    POST /api/apikeys/import

    请求

    
    {
      "fromBillId": "OTHER_BILL_ID",
      "toBillId": "B8K2L4P9Q0",
      "provider": "openai",
      "model": "gpt-4o"
    }
    

    说明

  • provider + model 省略时导入该账单全部 Key
  • 导入的是 Key 配置引用(非 Key 本身,Key 存储在用户级别)
  • 仅同步哪些 Key 对当前账单可用的配置

  • 关联 DB 表api_keys


    后续动作:调用 fetchKeys() 刷新状态


    ---


    拖拽调整 Key 优先级 → 优先级变更


    触发 API


    PATCH /api/apikeys/order/user

    请求

    
    {
      "billId": "B8K2L4P9Q0",
      "orders": [
        {
          "provider": "gemini",
          "model": "gemini-1.5-pro",
          "owner_type": "user",
          "owner_id": "U7X9R1P2A1",
          "priority": 1
        },
        {
          "provider": "openai",
          "model": "gpt-4o",
          "owner_type": "user",
          "owner_id": "U7X9R1P2A1",
          "priority": 2
        }
      ]
    }
    

    说明:批量更新用户在指定账单下的 Key 优先级顺序(用于 failover 顺序)


    关联 DB 表user_provider_order


    ---


    AI Prompt 设置(每个账单独立)


    说明:每个账单可以设置独立的 AI 对话 Prompt(Custom Prompt),由 BillPage 的「Custom Prompt」入口触发。


    > ⚠️ 已知问题:见 P13


    触发 API


    PUT /api/bills/:billId/prompt

    请求

    
    {
      "prompt": "你是一个专业的家庭财务顾问..."
    }
    

    权限:任意账单成员(owner / editor / viewer)均可设置


    后端处理UPDATE bill_members SET custom_prompt = :prompt, updated_at = NOW() WHERE bill_id = :billId AND user_id = :userId


    DB 表bill_members(注意:prompt 属于 bill_members 表,每个用户在每个账单有独立的 custom_prompt)


    ---


    退出登录(点击「退出登录」)


    触发 API


    POST /api/auth/logout

    请求

    
    {
      "refreshToken": ""
    }
    

    说明

  • 传 refreshToken 则只删除该条 Token
  • 不传则删除该用户全部 Token

  • 后端处理:删除 refresh_tokens 表中对应记录


    后续动作

    1. 清除 localStorage 中的 accessTokenrefreshToken

    2. 跳转至登录页 /login

    3. 重置所有 Context 状态


    ---


    账号注销 / 删除(若有)


    > 注:当前前端可能无账号注销入口,以下为后端已知端点说明


    DB 表users(删除后 CASCADE 至 billsbill_memberstransactionsapi_keys 等)


    ---


    游客升级(点击「升级为正式账号」)


    说明:游客在 SettingsPage 点击升级按钮,填写完整信息后提交


    触发 API


    POST /api/auth/upgrade-guest

    请求

    
    {
      "phone": "+8613812345678",
      "password": "123456",
      "passwordConfirm": "123456",
      "nickname": "张三",
      "email": "user@example.com",
      "emailCode": "123456",
      "captchaId": "...",
      "captchaAnswer": "ABCDE"
    }
    

    后端处理

    1. 确认当前用户是 is_guest=1

    2. 校验新手机号+邮箱未被他用户占用

    3. 校验邮箱验证码

    4. bcrypt 更新 password_hash

    5. 更新 users 表:is_guest=0

    6. 生成新 JWT(2h)


    DB 表users


    ---


    权限判断汇总


    操作权限API 端点

    |------|------|---------|

    查看个人资料任意登录用户GET /api/auth/me(AuthContext 注入)
    修改昵称任意登录用户PUT /api/auth/me/profile
    修改头像任意登录用户PUT /api/auth/me/profile
    切换支出颜色任意登录用户PUT /api/auth/me/profile
    查看 AI Key 列表任意登录用户GET /api/apikeys/user
    查看 Key 建议任意登录用户GET /api/apikeys/suggestions
    验证 Key任意登录用户POST /api/apikeys/verify/user
    保存/更新 Key任意登录用户PUT /api/apikeys/user
    切换共享状态任意登录用户PATCH /api/apikeys/user/share
    删除 Key任意登录用户DELETE /api/apikeys/user/:provider
    导入其他账单的 Key任意登录用户POST /api/apikeys/import
    更新 Key 优先级任意登录用户PATCH /api/apikeys/order/user
    设置 AI Prompt任意账单成员PUT /api/bills/:billId/prompt
    游客升级游客用户POST /api/auth/upgrade-guest
    退出登录任意登录用户POST /api/auth/logout