Merge branch 'master' of http://82.157.175.59:3000/GenarrativeAI/Genarrative
This commit is contained in:
172
docs/prd/PROFILE_FEEDBACK_ENTRY_PRD_2026-05-08.md
Normal file
172
docs/prd/PROFILE_FEEDBACK_ENTRY_PRD_2026-05-08.md
Normal file
@@ -0,0 +1,172 @@
|
||||
# “我的”页签帮助与反馈入口 PRD
|
||||
|
||||
更新时间:`2026-05-08`
|
||||
|
||||
## 0. 目标
|
||||
|
||||
在平台“我的”页签新增“反馈”入口。用户点击后进入独立路由 `/profile/feedback`,看到移动端优先的“帮助与反馈”表单页面,用于提交问题描述、上传问题截图凭证并选填联系电话。
|
||||
|
||||
本次目标是补齐用户反馈入口和前端提交流程,不重新发明新的个人中心系统,不在“我的”页签当前面板下方展开表单。
|
||||
|
||||
## 1. 参考图
|
||||
|
||||
计划参考图保存在:
|
||||
|
||||
`../.hermes/plans/assets/profile-feedback-reference-2026-05-08.png`
|
||||
|
||||
页面结构以该参考图为准:
|
||||
|
||||
1. 顶部白色导航栏,标题为“帮助与反馈”。
|
||||
2. 内容背景为浅灰色。
|
||||
3. 分区标题为“反馈问题”。
|
||||
4. 第一张白色圆角卡片为“问题描述”。
|
||||
5. 第二张白色圆角卡片为“上传凭证(提供问题截图)”。
|
||||
6. 第三张白色圆角卡片为“联系电话”。
|
||||
7. 底部为蓝色主按钮“提交”。
|
||||
8. 提交按钮下方为蓝色文本入口“查看反馈与投诉记录”。
|
||||
|
||||
## 2. 首版范围
|
||||
|
||||
### 2.1 包含
|
||||
|
||||
- “我的”页签常用功能区新增“反馈”入口。
|
||||
- 点击入口进入 `/profile/feedback` 独立路由。
|
||||
- 反馈页标题显示“帮助与反馈”。
|
||||
- 问题描述输入:
|
||||
- 最少 10 个字。
|
||||
- 最多 200 个字。
|
||||
- 实时显示 `当前字数/200`。
|
||||
- placeholder:`请填写10个字以上的问题描述以便我们提供更好的帮助,温馨提醒您请勿填写身份证号等个人隐私信息。`
|
||||
- 上传凭证:
|
||||
- 展示虚线上传方块。
|
||||
- 支持选择图片时,最多 4 张。
|
||||
- 前端可预览已选图片。
|
||||
- 不接后端时,提交只进入前端成功态。
|
||||
- 联系电话:
|
||||
- 选填。
|
||||
- placeholder:`选填,如您填写则将会同步开发者与您联系`。
|
||||
- 提交后显示成功态。
|
||||
- 返回后回到平台首页并定位“我的”页签。
|
||||
|
||||
### 2.2 不包含
|
||||
|
||||
- 不新增后端反馈存储接口。
|
||||
- 不新增 SpacetimeDB 表结构和 migration。
|
||||
- 不新增后台反馈记录管理页。
|
||||
- 不实现真实“反馈与投诉记录”列表。
|
||||
|
||||
如果后续要求真实存储反馈,需要另起后端 PRD/技术方案,覆盖 `shared-contracts`、`api-server`、SpacetimeDB 表与后台管理入口。
|
||||
|
||||
## 3. 入口设计
|
||||
|
||||
### 3.1 入口位置
|
||||
|
||||
入口放在“我的”页签常用功能区,和“每日任务 / 邀请好友 / 填邀请码 / 玩家社区”同级。
|
||||
|
||||
入口展示:
|
||||
|
||||
- 主标题:`反馈`
|
||||
- 副标题:`问题与建议`
|
||||
- 图标:可复用 `MessageCircle` 或类似消息图标。
|
||||
|
||||
### 3.2 未登录状态
|
||||
|
||||
首版默认未登录用户点击入口时触发登录弹窗,不进入反馈页。
|
||||
|
||||
原因:当前“我的”页签的数据与账号绑定,反馈如果未来接入后端,也应能关联提交账号。
|
||||
|
||||
## 4. 反馈页 UI
|
||||
|
||||
### 4.1 页面整体
|
||||
|
||||
- 移动端优先。
|
||||
- 背景为浅灰色或与现有平台浅色 surface 接近的背景。
|
||||
- 表单容器使用白色圆角卡片。
|
||||
- 桌面端居中展示,最大宽度不超过移动表单阅读范围,避免横向拉满。
|
||||
|
||||
### 4.2 顶部栏
|
||||
|
||||
- 标题:`帮助与反馈`。
|
||||
- 左侧返回/首页图标:点击返回平台首页“我的”页签。
|
||||
- 右侧胶囊控制区可不完全复刻;项目内若没有同类控件,保持简洁,不强行新增无实际功能按钮。
|
||||
|
||||
### 4.3 问题描述卡片
|
||||
|
||||
- 标题:`问题描述`。
|
||||
- 输入框类型:textarea。
|
||||
- 最小高度接近参考图的大文本区域。
|
||||
- 右下角字数:`0/200`。
|
||||
- 校验失败提示靠近卡片或提交按钮上方展示,不弹浏览器 alert。
|
||||
|
||||
### 4.4 上传凭证卡片
|
||||
|
||||
- 标题:`上传凭证(提供问题截图)`。
|
||||
- 上传入口为虚线边框方块。
|
||||
- 文案:
|
||||
- `上传凭证`
|
||||
- `(最多四张)`
|
||||
- 支持图片选择时,只允许 `image/*`。
|
||||
- 超过 4 张时提示:`最多上传四张凭证`。
|
||||
|
||||
### 4.5 联系电话卡片
|
||||
|
||||
- 标题:`联系电话`。
|
||||
- 输入框类型:text 或 tel。
|
||||
- 联系电话选填,不阻塞提交。
|
||||
- 最长 40 字符。
|
||||
|
||||
### 4.6 底部操作
|
||||
|
||||
- 主按钮:`提交`。
|
||||
- 按钮为蓝色圆角,宽度接近容器宽度。
|
||||
- 二级链接:`查看反馈与投诉记录`。
|
||||
- 首版无记录页时,该链接可以:
|
||||
- 隐藏;或
|
||||
- 保留并点击后显示轻量提示“反馈记录暂未开放”。
|
||||
|
||||
## 5. 路由与状态
|
||||
|
||||
- 新增页面阶段:`profile-feedback`。
|
||||
- 新增路由:`/profile/feedback`。
|
||||
- 浏览器直接访问 `/profile/feedback` 时应显示反馈页。
|
||||
- 点击页面返回时:
|
||||
- 设置平台 tab 为 `profile`。
|
||||
- 回到 `platform` 阶段。
|
||||
|
||||
## 6. 表单校验
|
||||
|
||||
提交时按以下顺序校验:
|
||||
|
||||
1. 问题描述去除首尾空白后少于 10 个字:提示 `请填写10个字以上的问题描述`。
|
||||
2. 问题描述超过 200 个字:提示 `问题描述不能超过 200 字`。
|
||||
3. 联系电话超过 40 字符:提示 `联系电话不能超过 40 字`。
|
||||
4. 上传凭证超过 4 张:提示 `最多上传四张凭证`。
|
||||
|
||||
校验通过后进入前端成功态。
|
||||
|
||||
## 7. 验收标准
|
||||
|
||||
- “我的”页签可看到“反馈”入口。
|
||||
- 已登录用户点击后进入 `/profile/feedback`。
|
||||
- 未登录用户点击后弹登录。
|
||||
- `/profile/feedback` 页面显示“帮助与反馈”。
|
||||
- 问题描述字数统计实时变化。
|
||||
- 空内容或少于 10 个字提交时显示校验错误。
|
||||
- 有效内容提交后显示成功态。
|
||||
- 上传凭证最多 4 张。
|
||||
- 联系电话为空时可以提交。
|
||||
- 返回后回到“我的”页签。
|
||||
- 页面在 390×844 移动端视口不横向溢出。
|
||||
- `npm run check:encoding`、`npm run typecheck`、定向测试通过。
|
||||
|
||||
## 8. 文件落点
|
||||
|
||||
- PRD:`docs/prd/PROFILE_FEEDBACK_ENTRY_PRD_2026-05-08.md`
|
||||
- 路由:`src/routing/appPageRoutes.ts`
|
||||
- 阶段类型:`src/components/platform-entry/platformEntryTypes.ts`
|
||||
- 反馈页:`src/components/platform-entry/PlatformFeedbackView.tsx`
|
||||
- 我的页签入口:`src/components/rpg-entry/RpgEntryHomeView.tsx`
|
||||
- 页面接入:`src/components/platform-entry/PlatformEntryFlowShellImpl.tsx`
|
||||
- 测试:
|
||||
- `src/routing/appPageRoutes.test.ts`
|
||||
- `src/components/platform-entry/PlatformFeedbackView.test.tsx`
|
||||
94
docs/technical/ADMIN_DATABASE_TABLE_QUERY_2026-05-08.md
Normal file
94
docs/technical/ADMIN_DATABASE_TABLE_QUERY_2026-05-08.md
Normal file
@@ -0,0 +1,94 @@
|
||||
# 后台数据库表查询技术方案(2026-05-08)
|
||||
|
||||
## 背景
|
||||
|
||||
后台“总览”页已经通过 `/admin/api/overview` 展示 SpacetimeDB 表统计,但只能看到表名、行数和统计状态。运营和排障时需要从统计行直接进入单表查询页,按基础条件快速查看真实行数据。
|
||||
|
||||
## 目标
|
||||
|
||||
- 在后台新增“表查询”页,支持所有 schema 表的只读查询。
|
||||
- “总览 / 表统计”中的每一行可点击跳转到对应表的查询页。
|
||||
- 提供基础查询能力:表选择、关键词搜索、JSON 条件过滤、条数限制、刷新、查看行详情。
|
||||
- 不修改 SpacetimeDB 表结构,不新增 reducer,不引入写操作。
|
||||
|
||||
## 后续增强
|
||||
|
||||
- 查询页增加“重置条件”快捷操作,便于运营快速回到默认筛选状态。
|
||||
- 行详情支持一键复制完整 JSON,减少人工选中复制的操作成本。
|
||||
- 查询页顶部增加轻量摘要,显示当前选表和可见列数,方便移动端快速确认上下文。
|
||||
|
||||
## 后端接口
|
||||
|
||||
### `GET /admin/api/database/tables`
|
||||
|
||||
鉴权:沿用 `require_admin_auth`。
|
||||
|
||||
数据来源:SpacetimeDB schema HTTP API。
|
||||
|
||||
响应:
|
||||
|
||||
```json
|
||||
{
|
||||
"tables": ["tracking_event", "user_account"],
|
||||
"fetchErrors": []
|
||||
}
|
||||
```
|
||||
|
||||
### `GET /admin/api/database/tables/{tableName}/rows`
|
||||
|
||||
鉴权:沿用 `require_admin_auth`。
|
||||
|
||||
Query:
|
||||
|
||||
- `limit`:默认 100,范围 1-500。
|
||||
- `search`:可选,前端关键词;后端返回行后在 JSON 文本中大小写不敏感过滤。
|
||||
- `filters`:可选 JSON object 字符串,例如 `{"user_id":"u1","enabled":true}`;后端返回行后按字段等值过滤。
|
||||
|
||||
响应:
|
||||
|
||||
```json
|
||||
{
|
||||
"tableName": "tracking_event",
|
||||
"columns": ["event_id", "event_key"],
|
||||
"rows": [
|
||||
{
|
||||
"cells": {
|
||||
"event_id": "event-1",
|
||||
"event_key": "daily_login"
|
||||
},
|
||||
"raw": ["event-1", "daily_login"]
|
||||
}
|
||||
],
|
||||
"totalReturned": 1,
|
||||
"limit": 100
|
||||
}
|
||||
```
|
||||
|
||||
实现约束:
|
||||
|
||||
- 表名必须来自 schema 且通过标识符安全校验,避免任意 SQL 注入。
|
||||
- SQL 固定为 `SELECT * FROM {tableName} LIMIT {limit}`;SpacetimeDB 2.2 HTTP SQL 不拼 `ORDER BY`。
|
||||
- 用户输入不直接拼入 SQL;关键词和条件在 API Server 内存中过滤。
|
||||
- private 表或 token 不可见时返回后台可读错误信息。
|
||||
- SpacetimeDB SQL 行和 SATS 值统一转成人可读 JSON:Option None 为 null,Some 展开为内部值,Timestamp 单元素数组展开为内部值,enum 可保留 tag/name 或原始数组文本。
|
||||
|
||||
## 前端页面
|
||||
|
||||
路由:`#tables`,导航名“表查询”。
|
||||
|
||||
页面能力:
|
||||
|
||||
- 表选择下拉,支持 URL hash `#tables?table=xxx` 直达指定表。
|
||||
- 查询表单:表名、关键词、JSON 条件、条数。
|
||||
- 查询结果表格横向滚动,移动端不撑坏布局。
|
||||
- 每行提供“详情”按钮,以独立弹层展示完整 JSON。
|
||||
- 总览表统计行点击后跳转到 `#tables?table={tableName}`。
|
||||
|
||||
## 验收
|
||||
|
||||
- `cd server-rs && cargo fmt -p api-server -p shared-contracts --check`
|
||||
- `cd server-rs && cargo test -p api-server admin_database -- --nocapture`
|
||||
- `npm run admin-web:typecheck`
|
||||
- `npm run admin-web:build`
|
||||
- `npm run check:encoding`
|
||||
- `git diff --check`
|
||||
@@ -0,0 +1,73 @@
|
||||
# 登录成功每日登录埋点闭环方案(2026-05-08)
|
||||
|
||||
## 背景
|
||||
|
||||
后台“埋点数据”需要能看到真实登录触发的 `daily_login` 埋点。此前方案 A 已把“读取任务中心时顺手写每日登录埋点”拆成独立 SpacetimeDB procedure:
|
||||
|
||||
- `record_daily_login_tracking_event_and_return`
|
||||
- `spacetime-client` 方法:`record_daily_login_tracking_event(user_id)`
|
||||
|
||||
但认证成功链路还没有调用该方法,因此当前只完成了“任务中心读取不污染登录埋点”,没有完成“用户真实登录写入每日登录埋点”。
|
||||
|
||||
## 现象
|
||||
|
||||
用户已经登录、cookie 未过期时,直接打开网页并不会触发每日登录埋点。原因是前端恢复登录态只读取 `/api/auth/me`,这条链路不会主动走 refresh cookie 续期,因此后端新的埋点写入点不会被触发。
|
||||
|
||||
## 修复思路
|
||||
|
||||
在 `AuthGate` 恢复已登录会话时,先主动调用一次 refresh 接口轮换 refresh cookie,再调用 `/api/auth/me` 读取当前会话。这样无论本地 access token 是否仍然有效,打开页面都会进入 refresh 续期链路,从而触发后端的 `daily_login` 埋点写入。
|
||||
|
||||
## 目标
|
||||
|
||||
在用户认证成功并创建 refresh session / access token 后,异步尝试写入每日登录埋点。
|
||||
|
||||
覆盖入口:
|
||||
|
||||
- 手机验证码登录:`POST /api/auth/phone/login`
|
||||
- 密码入口登录:`POST /api/auth/entry`
|
||||
- 重置密码后自动登录:`POST /api/auth/password/reset`
|
||||
- 微信 OAuth callback 登录:`GET /api/auth/wechat/callback`
|
||||
- 微信绑定手机号后激活/登录态刷新:`POST /api/auth/wechat/bind-phone`
|
||||
- refresh cookie 续期:`POST /api/auth/session/refresh`
|
||||
|
||||
## 设计约束
|
||||
|
||||
1. 埋点写入不能阻断登录成功响应。
|
||||
2. 只有认证成功并已创建会话后,或 refresh session rotate 成功并签发新 access token 后才记录。
|
||||
3. 失败只记 warning,继续返回 token / cookie。
|
||||
4. 写入统一收口,避免多个登录 handler 各自拼 procedure 调用。
|
||||
5. 不修改 SpacetimeDB 表结构,不需要更新 `migration.rs`。
|
||||
|
||||
## 实现方案
|
||||
|
||||
新增 `api-server` 内部 helper:
|
||||
|
||||
```rust
|
||||
record_daily_login_tracking_event_after_auth_success(
|
||||
state: &AppState,
|
||||
request_context: &RequestContext,
|
||||
user_id: &str,
|
||||
login_method: AuthLoginMethod,
|
||||
).await;
|
||||
```
|
||||
|
||||
该 helper:
|
||||
|
||||
- 调用 `state.spacetime_client().record_daily_login_tracking_event(user_id.to_string()).await`
|
||||
- 成功时记录 info
|
||||
- 失败时记录 warn,并明确“登录流程继续”
|
||||
|
||||
在各登录入口 `create_auth_session` 成功后调用该 helper。refresh cookie 续期在 `rotate_session` 和 `sign_access_token_for_user` 成功后调用同一个 helper,`login_method` 使用 refresh session 上保存的 `issued_by_provider`,避免把续期统一误标成 password。
|
||||
|
||||
## 验收
|
||||
|
||||
- `cargo test -p api-server auth_session -- --nocapture`
|
||||
- `cargo check -p api-server`
|
||||
- `cargo check -p spacetime-client`
|
||||
- `npm run check:encoding`
|
||||
- `git diff --check`
|
||||
- `npm run test -- AuthGate.test.tsx`
|
||||
|
||||
## 注意
|
||||
|
||||
`npm run dev` 是长期运行进程;如需本地 smoke,应启动后用 `/healthz` 和后台页面验证,不要等待该命令退出。
|
||||
Reference in New Issue
Block a user