Skip to content

feat(persona): user persona (casual/dev/team) — UI preference, not a role - #3

Merged
hades217 merged 1 commit into
mainfrom
feat/user-persona
May 16, 2026
Merged

feat(persona): user persona (casual/dev/team) — UI preference, not a role#3
hades217 merged 1 commit into
mainfrom
feat/user-persona

Conversation

@hades217

Copy link
Copy Markdown

Summary

为非技术 / 非 admin 用户重做 dashboard 体验,不动权限模型。新增 persona 字段(casual / dev / team)存在 users.setting JSON 里,只影响 UI 不影响后端权限。

三种 persona

Casual 🎨 Dev 💻 Team 👥 Admin (role)
Sidebar chat (playground / chat)
Sidebar console (token / log / mj / task)
Sidebar personal (wallet / profile)
Sidebar admin ✅ (role 控制)
Create Key 默认 mode Simple Advanced Advanced Advanced
Advanced 里 Group / Cross-group / Quantity n/a ❌ 隐藏 ❌ 隐藏 ✅ 显示
注册后 default route /playground /keys /keys /dashboard/overview

关键设计

  • 新账号:backend Register 自动写入 setting.persona = "unset",第一次进 dashboard 弹出 PersonaPickerDialog(强制选,没有关闭按钮)
  • 旧账号persona 字段 absent → 静默默认 dev,sidebar 跟今天一模一样、不打扰
  • Profile 切换/profile 的 Sidebar Modules 卡顶部加了 "Quick start preset" 3 按钮,选完一键应用 sidebar + 持久化 persona
  • 后端零侵入:复用现有 PUT /api/user/setting 端点,不加新路由;只是 dto.UserSetting 多了一个字段

"Developer 像分销商" 修复(顺手)

Advanced 模式下,对非 admin 用户隐藏:

  • Group(jr-academy / airbotix-kids 这类分销倍率组)
  • Cross-group retry(多通道容灾开关)
  • Quantity(批量建 Key,分销商场景)

Admin role 完全保留这些字段,运营功能不动。

Test plan

新用户全流程

  • 注册新账号 → 跳 /sign-in → 登录 → 落到 /dashboard/overview
  • PersonaPickerDialog 自动弹出,3 张卡片可见,背景模糊,关闭按钮不存在
  • 选 🎨 Casual → modal 关闭 → URL 跳到 /playground → sidebar 缩成 Playground/Wallet/Profile
  • 刷新页面 → 不再弹 picker(已持久化)

老用户保护

  • 用已有账号登录 → 不弹 picker → sidebar 跟今天完全一样
  • /profile → Sidebar Modules 卡顶部能看到 "Quick start preset" 三按钮

Profile 切换

  • /profile 点 🎨 Casual → console 区一键消失 → 刷新仍消失
  • 再点 💻 Developer → 恢复
  • 切换时 toast 提示 "Switched preset"

非 admin Advanced 字段隐藏

  • 用普通用户(role=1)创建 Key → 弹 mode picker → 选 Advanced
  • 不应该看到:Group、Cross-group retry、Quantity
  • 应该看到:Name、Allowed models、Expiration、Quota、IP whitelist

Admin 不受影响

  • Admin 用户创建 Key Advanced → 全部字段可见(Group / Cross-group / Quantity / 等)

文件

新增

  • web/default/src/components/persona-picker-dialog.tsx — 3 卡片 modal
  • web/default/src/components/persona-picker-host.tsx — 挂载 + 持久化逻辑
  • web/default/src/features/profile/lib/persona-presets.ts — PERSONA_PRESETS + resolveEffectivePersona
  • web/default/src/hooks/use-persona.ts — usePersona / useShouldPromptPersona

修改

  • dto/user_settings.go — +Persona string
  • controller/user.go — Register 初始化 setting.persona="unset"
  • web/default/src/features/profile/types.ts — UserSettings + UpdateUserSettingsRequest 加 persona / sidebar_modules
  • web/default/src/features/profile/components/sidebar-modules-card.tsx — Quick start preset 行
  • web/default/src/components/layout/components/authenticated-layout.tsx — mount PersonaPickerHost
  • web/default/src/features/keys/components/api-keys-mutate-drawer.tsx — 用 useIsAdmin 隐藏 Group/Cross-group/Quantity
  • web/default/src/i18n/locales/{en,zh}.json — 17 新 key

12 files changed, 662 insertions(+), 4 deletions(-)

🤖 Generated with Claude Code

…role

Adds a `persona` UI-tailoring preference to `users.setting` JSON so the
dashboard can adapt for non-technical end users without doubling
permissions. Same backend role, different sidebar/defaults per user.

Three personas:
- casual : non-tech end users. Sidebar shrinks to chat + playground +
  wallet + profile; the Create Key flow defaults to Simple; default
  landing route is /playground (in-browser chat so they can try AI
  without setting up a client).
- dev    : developers. Full non-admin sidebar (chat + console + personal).
  Create Key defaults to Advanced; default landing route is /keys.
- team   : team / enterprise. Same sidebar as dev for now; reserved
  for future audit / sub-account features.

Storage:
- New `Persona string` field on dto.UserSetting (with omitempty).
- controller.Register seeds new accounts with persona="unset" so the
  frontend can distinguish "new account, needs picker" from "legacy
  user, persona key absent → default to dev silently".

Frontend:
- New components/persona-picker-dialog.tsx — 3-card modal with explicit
  descriptions and an example footnote per persona.
- New components/persona-picker-host.tsx mounted in AuthenticatedLayout
  detects setting.persona === "unset" and prompts the picker (mandatory:
  dismissible=false). On pick: PUT /api/user/setting with persona +
  matching sidebar_modules preset, hydrate auth-store, navigate to
  preset's default route only if user is on a generic landing.
- New hooks/use-persona.ts: usePersona() returns the effective persona
  (legacy fallback = dev), useShouldPromptPersona() returns the sentinel
  check for the picker mount.
- New features/profile/lib/persona-presets.ts: PERSONA_PRESETS map +
  resolveEffectivePersona helper (single source of truth for "what does
  this user's setting JSON mean").
- Profile / Sidebar Modules card gets a "Quick start preset" 3-button
  row at the top — picking writes persona + sidebar_modules in one PUT
  and re-hydrates the granular switches below to match.

Cleanup of B2B2C reseller UI for non-admin users:
- Hide Group, Cross-group retry, and Quantity (batch) fields from
  Advanced mode for non-admin role via useIsAdmin(). These are operator
  concepts a real developer doesn't need. Admin still sees them.

i18n: 17 new en + zh keys for the picker and quick-start preset row.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
@hades217
hades217 force-pushed the feat/user-persona branch from 21a1ef0 to e5169f8 Compare May 16, 2026 08:28
@hades217
hades217 merged commit 2c03e35 into main May 16, 2026
hades217 added a commit that referenced this pull request Jun 19, 2026
Multi-agent research synthesis: mirrors the Stripe auto-topup path for
Airwallex (Customer + PaymentConsent + PaymentMethod), with data-model
changes, webhook hardening, provider-split charge seam, AUD/USD currency
unification, risks, test plan, and a 9-PR phased rollout where only the
final PR enables real off-session charging. Design only — no code shipped.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant