Add backend feedback submission and image preview
Some checks failed
CI / verify (push) Has been cancelled
Some checks failed
CI / verify (push) Has been cancelled
This commit is contained in:
@@ -6,7 +6,7 @@
|
||||
|
||||
在平台“我的”页签新增“反馈”入口。用户点击后进入独立路由 `/profile/feedback`,看到移动端优先的“帮助与反馈”表单页面,用于提交问题描述、上传问题截图凭证并选填联系电话。
|
||||
|
||||
本次目标是补齐用户反馈入口和前端提交流程,不重新发明新的个人中心系统,不在“我的”页签当前面板下方展开表单。
|
||||
本次目标是补齐用户反馈入口、图片预览、后端提交接口和 SpacetimeDB 持久化闭环,不重新发明新的个人中心系统,不在“我的”页签当前面板下方展开表单。
|
||||
|
||||
## 1. 参考图
|
||||
|
||||
@@ -16,8 +16,8 @@
|
||||
|
||||
页面结构以该参考图为准:
|
||||
|
||||
1. 顶部白色导航栏,标题为“帮助与反馈”。
|
||||
2. 内容背景为浅灰色。
|
||||
1. 页面顶部保留项目风格返回按钮和标题“帮助与反馈”,不保留无实际功能的仿客户端顶部栏。
|
||||
2. 内容背景、卡片、按钮和状态色使用现有平台主题变量,避免硬编码成与主站不一致的蓝灰色页面。
|
||||
3. 分区标题为“反馈问题”。
|
||||
4. 第一张白色圆角卡片为“问题描述”。
|
||||
5. 第二张白色圆角卡片为“上传凭证(提供问题截图)”。
|
||||
@@ -41,21 +41,19 @@
|
||||
- 展示虚线上传方块。
|
||||
- 支持选择图片时,最多 4 张。
|
||||
- 前端可预览已选图片。
|
||||
- 不接后端时,提交只进入前端成功态。
|
||||
- 已选图片使用 Data URL 预览,并随提交请求作为首版反馈凭证入库。
|
||||
- 联系电话:
|
||||
- 选填。
|
||||
- placeholder:`选填,如您填写则将会同步开发者与您联系`。
|
||||
- 提交后显示成功态。
|
||||
- 提交后通过 `POST /api/profile/feedback` 写入 SpacetimeDB,接口成功后显示成功态。
|
||||
- 返回后回到平台首页并定位“我的”页签。
|
||||
|
||||
### 2.2 不包含
|
||||
|
||||
- 不新增后端反馈存储接口。
|
||||
- 不新增 SpacetimeDB 表结构和 migration。
|
||||
- 不新增后台反馈记录管理页。
|
||||
- 不实现真实“反馈与投诉记录”列表。
|
||||
|
||||
如果后续要求真实存储反馈,需要另起后端 PRD/技术方案,覆盖 `shared-contracts`、`api-server`、SpacetimeDB 表与后台管理入口。
|
||||
后端接入细节以 [`docs/technical/PROFILE_FEEDBACK_BACKEND_INTEGRATION_2026-05-08.md`](../technical/PROFILE_FEEDBACK_BACKEND_INTEGRATION_2026-05-08.md) 为准。
|
||||
|
||||
## 3. 入口设计
|
||||
|
||||
@@ -80,15 +78,14 @@
|
||||
### 4.1 页面整体
|
||||
|
||||
- 移动端优先。
|
||||
- 背景为浅灰色或与现有平台浅色 surface 接近的背景。
|
||||
- 表单容器使用白色圆角卡片。
|
||||
- 背景、表单容器、输入框、提示和按钮复用 `platform-*` 主题变量。
|
||||
- 桌面端居中展示,最大宽度不超过移动表单阅读范围,避免横向拉满。
|
||||
|
||||
### 4.2 顶部栏
|
||||
### 4.2 返回区
|
||||
|
||||
- 标题:`帮助与反馈`。
|
||||
- 左侧返回/首页图标:点击返回平台首页“我的”页签。
|
||||
- 右侧胶囊控制区可不完全复刻;项目内若没有同类控件,保持简洁,不强行新增无实际功能按钮。
|
||||
- 左侧返回按钮:点击返回平台首页“我的”页签。
|
||||
- 不展示右侧胶囊控制区、假系统按钮或无实际功能顶部栏。
|
||||
|
||||
### 4.3 问题描述卡片
|
||||
|
||||
@@ -107,6 +104,8 @@
|
||||
- `(最多四张)`
|
||||
- 支持图片选择时,只允许 `image/*`。
|
||||
- 超过 4 张时提示:`最多上传四张凭证`。
|
||||
- 单张图片最大 1MB,总大小最大 4MB。
|
||||
- 选择图片后必须立即展示缩略图预览,删除后从待提交凭证中移除。
|
||||
|
||||
### 4.5 联系电话卡片
|
||||
|
||||
@@ -142,7 +141,7 @@
|
||||
3. 联系电话超过 40 字符:提示 `联系电话不能超过 40 字`。
|
||||
4. 上传凭证超过 4 张:提示 `最多上传四张凭证`。
|
||||
|
||||
校验通过后进入前端成功态。
|
||||
校验通过后调用 `POST /api/profile/feedback`,请求成功后进入成功态。
|
||||
|
||||
## 7. 验收标准
|
||||
|
||||
@@ -154,6 +153,9 @@
|
||||
- 空内容或少于 10 个字提交时显示校验错误。
|
||||
- 有效内容提交后显示成功态。
|
||||
- 上传凭证最多 4 张。
|
||||
- 上传凭证选择后显示图片预览。
|
||||
- 有效反馈提交后写入 `profile_feedback_submission` 表。
|
||||
- 提交接口返回 `feedbackId`、状态、提交时间和凭证元数据。
|
||||
- 联系电话为空时可以提交。
|
||||
- 返回后回到“我的”页签。
|
||||
- 页面在 390×844 移动端视口不横向溢出。
|
||||
@@ -165,8 +167,16 @@
|
||||
- 路由:`src/routing/appPageRoutes.ts`
|
||||
- 阶段类型:`src/components/platform-entry/platformEntryTypes.ts`
|
||||
- 反馈页:`src/components/platform-entry/PlatformFeedbackView.tsx`
|
||||
- 前端 profile client:`src/services/rpg-entry/rpgProfileClient.ts`
|
||||
- 我的页签入口:`src/components/rpg-entry/RpgEntryHomeView.tsx`
|
||||
- 页面接入:`src/components/platform-entry/PlatformEntryFlowShellImpl.tsx`
|
||||
- 共享契约:`packages/shared/src/contracts/runtime.ts`、`server-rs/crates/shared-contracts/src/runtime.rs`
|
||||
- 后端 API:`server-rs/crates/api-server/src/runtime_profile.rs`
|
||||
- SpacetimeDB:`server-rs/crates/spacetime-module/src/runtime/profile.rs`
|
||||
- 领域规则:`server-rs/crates/module-runtime/src/*`
|
||||
- 测试:
|
||||
- `src/routing/appPageRoutes.test.ts`
|
||||
- `src/components/platform-entry/PlatformFeedbackView.test.tsx`
|
||||
- `src/services/rpg-entry/rpgProfileClient.test.ts`
|
||||
- `server-rs/crates/module-runtime`
|
||||
- `server-rs/crates/api-server/src/runtime_profile.rs`
|
||||
|
||||
@@ -0,0 +1,57 @@
|
||||
# 个人反馈后端接入方案
|
||||
|
||||
更新时间:`2026-05-08`
|
||||
|
||||
## 目标
|
||||
|
||||
`/profile/feedback` 不再停留在前端成功态,提交时必须经过 `api-server` 鉴权、`spacetime-client` facade、`spacetime-module` procedure,并持久化到 SpacetimeDB。
|
||||
|
||||
## 接口
|
||||
|
||||
- 路由:`POST /api/profile/feedback`
|
||||
- 鉴权:必须登录,用户 ID 取 `AuthenticatedAccessToken`,前端不得上传或伪造 `userId`。
|
||||
- 请求体:
|
||||
- `description`:必填,trim 后 10 至 200 字符。
|
||||
- `contactPhone`:选填,trim 后最多 40 字符。
|
||||
- `evidenceItems`:选填,最多 4 张图片。
|
||||
- 每张凭证包含 `fileName`、`contentType`、`sizeBytes`、`dataUrl`。
|
||||
- 响应体:
|
||||
- `feedback.feedbackId`
|
||||
- `feedback.status`
|
||||
- `feedback.createdAt`
|
||||
- `feedback.evidenceItems` 只回传凭证元数据,不回显 Data URL。
|
||||
|
||||
## 表结构
|
||||
|
||||
新增私有表 `profile_feedback_submission`:
|
||||
|
||||
- `feedback_id PK: String`
|
||||
- `user_id: String`
|
||||
- `description: String`
|
||||
- `contact_phone: Option<String>`
|
||||
- `evidence_json: String`
|
||||
- `status: RuntimeProfileFeedbackStatus`
|
||||
- `created_at: Timestamp`
|
||||
- `updated_at: Timestamp`
|
||||
- 索引:`user_id`、`(user_id, created_at)`
|
||||
|
||||
`evidence_json` 保存首版图片凭证快照,后续如果迁移 OSS,应保持 HTTP 契约不变,仅替换内部 evidence 存储字段。
|
||||
|
||||
## 分层落点
|
||||
|
||||
- `shared-contracts`:冻结 HTTP DTO。
|
||||
- `module-runtime`:负责输入归一化、长度限制、图片数量/大小/Data URL 前缀校验、反馈 ID 和 evidence ID 生成、响应记录组装。
|
||||
- `spacetime-module`:新增 table 与 `submit_profile_feedback_and_return` procedure;只做事务写入和表到快照映射。
|
||||
- `spacetime-client`:新增 `submit_profile_feedback` facade,不让 `api-server` 直接依赖生成绑定。
|
||||
- `api-server`:新增鉴权 POST route,并对该 route 单独放宽 JSON body 上限。
|
||||
- 前端:`PlatformFeedbackView` 只负责临时表单状态、图片预览和调用 profile client;正式提交结果以后端返回为准。
|
||||
- 绑定生成:Windows 本地如遇 `sccache` 远端缓存被网络沙箱拦截,可临时使用仓库内短路径 `GENARRATIVE_BINDGEN_TEMP_ROOT` 并设置 `CARGO_BUILD_RUSTC_WRAPPER` 到本地 rustc passthrough wrapper 后重跑生成,不修改 `server-rs/.cargo/config.toml`。
|
||||
|
||||
## 验收
|
||||
|
||||
- 图片选择后能在页面看到缩略图。
|
||||
- 有效表单调用 `POST /api/profile/feedback` 并写入 `profile_feedback_submission`。
|
||||
- 未登录提交返回 `401`。
|
||||
- 超过图片数量、单张大小、总大小或非法 Data URL 时返回清晰校验错误。
|
||||
- `migration.rs`、SpacetimeDB 表目录、生成绑定同步更新。
|
||||
- 定向前端测试、Rust 领域测试和 API 认证测试通过。
|
||||
@@ -5,6 +5,7 @@
|
||||
## 文档列表
|
||||
|
||||
- [RUST_WORKSPACE_DEPENDENCY_CONSOLIDATION_2026-05-07.md](./RUST_WORKSPACE_DEPENDENCY_CONSOLIDATION_2026-05-07.md):记录 `server-rs` Cargo 依赖集中配置口径,第三方版本和 workspace 内部 crate path 统一维护在根 `server-rs/Cargo.toml`,成员 crate 只保留 feature/optional 差异。
|
||||
- [PROFILE_FEEDBACK_BACKEND_INTEGRATION_2026-05-08.md](./PROFILE_FEEDBACK_BACKEND_INTEGRATION_2026-05-08.md):冻结“我的”页签帮助与反馈入口的后端接入方案,覆盖 `POST /api/profile/feedback`、`profile_feedback_submission`、凭证图片 Data URL 校验和前端预览/提交边界。
|
||||
- [API_SERVER_EXTERNAL_SERVICE_ENV_CONFIG_2026-05-07.md](./API_SERVER_EXTERNAL_SERVICE_ENV_CONFIG_2026-05-07.md):冻结 api-server 外部服务配置边界,公共服务 URL 可保留代码默认值,非公共模型名和私有网关 URL 统一通过环境变量注入。
|
||||
- [PROFILE_TASK_AND_TRACKING_SYSTEM_2026-05-03.md](./PROFILE_TASK_AND_TRACKING_SYSTEM_2026-05-03.md):冻结个人任务与埋点系统首版方案,明确 `tracking_event`、`tracking_daily_stat`、`profile_task_config`、任务进度、领奖记录和光点钱包流水的边界。
|
||||
- [SQUARE_HOLE_IMAGE_SLOT_AND_RUNTIME_INTERACTION_FIX_2026-05-06.md](./SQUARE_HOLE_IMAGE_SLOT_AND_RUNTIME_INTERACTION_FIX_2026-05-06.md):记录方洞挑战结果页图片槽位局部生成、洞口图历史素材、运行态拖拽与点击投放交互的修正口径。
|
||||
|
||||
@@ -24,7 +24,7 @@ spacetime sql <db> "SELECT * FROM custom_world_gallery_entry"
|
||||
| --- | --- |
|
||||
| 运维迁移 | `database_migration_operator`, `database_migration_import_chunk` |
|
||||
| 认证 | `auth_store_snapshot`, `user_account`, `auth_identity`, `refresh_session` |
|
||||
| 运行时档案 | `runtime_setting`, `runtime_snapshot`, `user_browse_history`, `profile_dashboard_state`, `profile_wallet_ledger`, `analytics_date_dimension`, `tracking_event`, `tracking_daily_stat`, `profile_task_config`, `profile_task_progress`, `profile_task_reward_claim`, `profile_redeem_code`, `profile_redeem_code_usage`, `profile_invite_code`, `profile_referral_relation`, `profile_played_world`, `profile_membership`, `profile_recharge_order`, `profile_save_archive` |
|
||||
| 运行时档案 | `runtime_setting`, `runtime_snapshot`, `user_browse_history`, `profile_dashboard_state`, `profile_wallet_ledger`, `analytics_date_dimension`, `tracking_event`, `tracking_daily_stat`, `profile_task_config`, `profile_task_progress`, `profile_task_reward_claim`, `profile_redeem_code`, `profile_redeem_code_usage`, `profile_invite_code`, `profile_referral_relation`, `profile_played_world`, `profile_membership`, `profile_recharge_order`, `profile_feedback_submission`, `profile_save_archive` |
|
||||
| RPG 运行时 | `story_session`, `story_event`, `npc_state`, `inventory_slot`, `battle_state`, `treasure_record`, `quest_record`, `quest_log`, `player_progression`, `chapter_progression` |
|
||||
| 世界创作 | `custom_world_profile`, `custom_world_session`, `custom_world_agent_session`, `custom_world_agent_message`, `custom_world_agent_operation`, `custom_world_draft_card`, `custom_world_gallery_entry` |
|
||||
| 拼图 | `puzzle_agent_session`, `puzzle_agent_message`, `puzzle_work_profile`, `puzzle_event`, `puzzle_runtime_run`, `puzzle_leaderboard_entry` |
|
||||
@@ -333,6 +333,18 @@ SELECT * FROM profile_recharge_order WHERE order_id = '<order_id>';
|
||||
SELECT * FROM profile_recharge_order WHERE user_id = '<user_id>' ORDER BY created_at DESC;
|
||||
```
|
||||
|
||||
### `profile_feedback_submission`
|
||||
|
||||
- 作用:保存“我的”页签帮助与反馈提交记录,关联当前登录用户的问题描述、选填联系电话和图片凭证快照。
|
||||
- 结构:`feedback_id PK: String`, `user_id: String`, `description: String`, `contact_phone: Option<String>`, `evidence_json: String`, `status: RuntimeProfileFeedbackStatus`, `created_at: Timestamp`, `updated_at: Timestamp`。
|
||||
- 索引:`user_id`, `(user_id, created_at)`。
|
||||
- 访问边界:私有表。前端只通过 `POST /api/profile/feedback` 提交,HTTP 回包只返回凭证元数据,不回显 `evidence_json` 中的 Data URL。
|
||||
|
||||
```sql
|
||||
SELECT * FROM profile_feedback_submission WHERE feedback_id = '<feedback_id>';
|
||||
SELECT * FROM profile_feedback_submission WHERE user_id = '<user_id>' ORDER BY created_at DESC;
|
||||
```
|
||||
|
||||
### `profile_save_archive`
|
||||
|
||||
- 作用:用户存档列表,保存世界信息、封面、当前状态 JSON 和剧情 JSON。
|
||||
|
||||
Reference in New Issue
Block a user