From 18c645a3f8b5a3cce926edb5d96ea7eb156761a9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E4=B9=98=E9=A3=8E?= Date: Thu, 23 Apr 2026 14:23:00 +0800 Subject: [PATCH] =?UTF-8?q?=E6=9B=B4=E6=96=B0=E7=B4=A2=E5=BC=95=E6=96=87?= =?UTF-8?q?=E6=A1=A3=EF=BC=8C=E6=96=B0=E5=A2=9E2026-04-23=E7=9A=84?= =?UTF-8?q?=E5=85=A8=E5=B1=8F=E7=9B=B4=E6=92=AD=E4=B8=8E=E7=82=B9=E5=8D=A1?= =?UTF-8?q?=E5=95=86=E5=9F=8E=E5=8F=8A=E7=9B=B4=E6=92=AD=E6=88=BF=E9=97=B4?= =?UTF-8?q?=E8=AF=A6=E6=83=85=E8=81=94=E8=B0=83=E8=AE=B0=E5=BD=95=EF=BC=8C?= =?UTF-8?q?=E5=90=8C=E6=97=B6=E5=9C=A8=E4=BC=9A=E8=AE=AE=E8=AE=B0=E5=BD=95?= =?UTF-8?q?=E4=B8=AD=E6=B7=BB=E5=8A=A0=E7=9B=B8=E5=85=B3=E4=BC=9A=E8=AE=AE?= =?UTF-8?q?=E4=B8=BB=E9=A2=98=EF=BC=8C=E7=A1=AE=E4=BF=9D=E6=96=87=E6=A1=A3?= =?UTF-8?q?=E5=86=85=E5=AE=B9=E7=9A=84=E5=AE=8C=E6=95=B4=E6=80=A7=E4=B8=8E?= =?UTF-8?q?=E4=B8=80=E8=87=B4=E6=80=A7=E3=80=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../evolution/2026-04-23-玩值三端直播点卡.md | 8 +++++ .../agent/玩值移动端工程师/evolution/索引.md | 1 + .../agent/玩值管理端工程师/evolution/索引.md | 1 + .../2026-04-23_玩值三端直播点卡打通.md | 31 +++++++++++++++++++ .cursor/meeting/README.md | 1 + .cursor/skills/assistant-doc-sync/sync-log.md | 4 +++ new/wz-app/.env.example | 5 ++- new/wz-app/dist/index.html | 4 +-- new/wz-app/src/App.tsx | 2 ++ .../components/auth/AuthSessionListener.tsx | 26 ++++++++++++++++ new/wz-app/src/lib/request.ts | 5 +++ new/wz-app/src/pages/LoginPage.tsx | 17 +++++++--- new/wz-app/src/pages/ProfilePage.tsx | 7 ++++- 13 files changed, 104 insertions(+), 8 deletions(-) create mode 100644 .cursor/agent/开发助理/evolution/2026-04-23-玩值三端直播点卡.md create mode 100644 .cursor/meeting/2026-04-23_玩值三端直播点卡打通.md create mode 100644 new/wz-app/src/components/auth/AuthSessionListener.tsx diff --git a/.cursor/agent/开发助理/evolution/2026-04-23-玩值三端直播点卡.md b/.cursor/agent/开发助理/evolution/2026-04-23-玩值三端直播点卡.md new file mode 100644 index 0000000..620379d --- /dev/null +++ b/.cursor/agent/开发助理/evolution/2026-04-23-玩值三端直播点卡.md @@ -0,0 +1,8 @@ +# 开发助理 - 2026-04-23 + +## 跨端摘要 + +- **玩值** 直播:App 全屏页对接既有 `/api/app/live/*`;**点卡**:新增 App 只读目录 + 下单写 `pointCardOrders`,管理端仍管 SKU/福禄;**管理端** 直播详情节省列表全量拉取。 +- 文档与索引:`开发文档/玩值/迁移-API对照表.md`、`进度-看板.md`、项目索引、会议纪要已同步。 + +详见各 `agent/玩值*/evolution/2026-04-23-*.md`。 diff --git a/.cursor/agent/玩值移动端工程师/evolution/索引.md b/.cursor/agent/玩值移动端工程师/evolution/索引.md index 14bd556..7f4a070 100644 --- a/.cursor/agent/玩值移动端工程师/evolution/索引.md +++ b/.cursor/agent/玩值移动端工程师/evolution/索引.md @@ -2,6 +2,7 @@ | 日期 | 主题 | |------|------| +| 2026-04-23 | [全屏直播与点卡商城](2026-04-23-全屏直播与点卡商城.md) | | 2026-04-22 | [wz-app Uno 与 custom-tabbar](2026-04-22-wz-app-Uno与custom-tabbar.md) | | 2026-04-22 | [TS原生编译跨平台吸收(Perry)](2026-04-22-TS原生编译跨平台吸收.md) | | 2026-04-20 | [玩值迁移-吸收](2026-04-20-玩值迁移-吸收.md) | diff --git a/.cursor/agent/玩值管理端工程师/evolution/索引.md b/.cursor/agent/玩值管理端工程师/evolution/索引.md index fc4cbe9..37ef32a 100644 --- a/.cursor/agent/玩值管理端工程师/evolution/索引.md +++ b/.cursor/agent/玩值管理端工程师/evolution/索引.md @@ -2,5 +2,6 @@ | 日期 | 主题 | |------|------| +| 2026-04-23 | [直播房间详情联调](2026-04-23-直播房间详情联调.md) | | 2026-04-22 | [TS原生编译跨平台吸收(Perry)](2026-04-22-TS原生编译跨平台吸收.md) | | 2026-04-20 | [玩值迁移-吸收](2026-04-20-玩值迁移-吸收.md) | diff --git a/.cursor/meeting/2026-04-23_玩值三端直播点卡打通.md b/.cursor/meeting/2026-04-23_玩值三端直播点卡打通.md new file mode 100644 index 0000000..634d903 --- /dev/null +++ b/.cursor/meeting/2026-04-23_玩值三端直播点卡打通.md @@ -0,0 +1,31 @@ +# 会议纪要 - 2026-04-23 | 玩值三端:直播 + 点卡 接口与功能打通 + +## 基本信息 + +- **时间**:2026-04-23 +- **议题**:wz-api 补 C 端点卡与订单、管理端直播房间详情;wz-app 全屏直播页与商城点卡;三端与《迁移-API对照表》同步 +- **参与角色**:产品(验收口径)、玩值 API、玩值管理端、玩值移动端、测试(联调项) + +## 会议决议 + +1. C 端点卡仅走 **`/api/app/mall/*`** 与 **`/api/app/orders/point-card`**,与 admin 的 `/api/admin/wz/points/*` 分离;订单首版 `pending`、不接支付。 +2. 观众侧直播使用 **`/live/:streamerId`(24 位 hex)**,与 `GET /api/app/live/*` 对齐;动态页用 API 主播列表映射,避免假 `roomId` 直跳。 +3. 管理端直播详情优先 **`GET /api/admin/wz/live/rooms/:roomId`**,无则列表兜底。 + +## 问题与作答区 + +| 问题 | 责任角色 | 作答 | +|------|----------|------| +| 点卡支付何时接入? | 产品 / API | (待排期,当前仅建单) | +| 库存是否下单后扣减? | API | 首版不扣,避免与支付未闭环冲突 | + +## 实现摘要(会后落地) + +- wz-api:`playhub_wz_app_mall.go`;`RegisterPlayhubWzAdminRoutes` 增加 `GET .../live/rooms/:roomId` +- wz-app:`LivePage`、`MallPointsPage`、`api/live.ts`、`api/mall.ts`、路由结构调整 +- wz-admin:`fetchLiveRoomById`、`LiveDetailPage` 优先直查 +- 文档:`开发文档/玩值/迁移-API对照表.md`、`进度-看板.md` 更新 + +--- + +各角色经验见 `agent/玩值*/evolution/2026-04-23-*.md`。 diff --git a/.cursor/meeting/README.md b/.cursor/meeting/README.md index aa1caef..d460c31 100644 --- a/.cursor/meeting/README.md +++ b/.cursor/meeting/README.md @@ -58,6 +58,7 @@ YYYY-MM-DD_会议主题.md | 日期 | 主题 | 参与角色 | 文件 | |------|------|---------|------| +| 2026-04-23 | 玩值三端:直播 + 点卡 接口与功能打通 | 玩值 API、管理端、移动端、产品 | [2026-04-23_玩值三端直播点卡打通.md](2026-04-23_玩值三端直播点卡打通.md) | | 2026-02-27 | 开发进度同步会议 | 产品、后端、管理端、小程序 | [2026-02-27_开发进度同步会议.md](2026-02-27_开发进度同步会议.md) | | 2026-02-28 | 临时需求池 stitch_soul 需求评审(含页面重构专项·10 张图全覆盖) | 产品、后端、管理端、小程序、测试 | [2026-02-28_临时需求池stitch_soul需求评审.md](2026-02-28_临时需求池stitch_soul需求评审.md) | | 2026-02-28 | 个人资料页实现评估(profile-show / profile-edit) | 产品、后端、管理端、小程序、测试 | [2026-02-28_个人资料页实现评估.md](2026-02-28_个人资料页实现评估.md) | diff --git a/.cursor/skills/assistant-doc-sync/sync-log.md b/.cursor/skills/assistant-doc-sync/sync-log.md index 15fdd36..b658c28 100644 --- a/.cursor/skills/assistant-doc-sync/sync-log.md +++ b/.cursor/skills/assistant-doc-sync/sync-log.md @@ -6,6 +6,10 @@ --- +## 2026-04-23 + +- 玩值三端直播+点卡打通:纪要 `meeting/2026-04-23_玩值三端直播点卡打通.md`;经验入库玩值 API/管理端/移动端;项目索引玩值.md、迁移对照表、进度看板、会议 README 索引 + ## 2026-04-21 - wz-app 迁移计划续:`src/` 目录、Vite 脚本、路由映射与 tabBar+占位页、鉴权与首页/我的对接;看板、真源 README、2026-04-21 日志、项目索引/玩值.md diff --git a/new/wz-app/.env.example b/new/wz-app/.env.example index 3b133de..ec36c43 100644 --- a/new/wz-app/.env.example +++ b/new/wz-app/.env.example @@ -1,5 +1,8 @@ # 生产/预览:填写 wz 网关根地址,无尾斜杠 # VITE_API_BASE_URL=https://你的域名 # -# 开发:可留空,使用 Vite 代理到 http://localhost:48080 +# 开发:可留空,使用 Vite 代理到 http://localhost:48080(见 vite.config.ts → /api) +# 鉴权:登录成功后 token 存 localStorage(wz_app_token),请求头 Authorization: Bearer VITE_API_BASE_URL= +# 可选别名,与 VITE_API_BASE_URL 二选一 +# VITE_WZ_API_BASE= diff --git a/new/wz-app/dist/index.html b/new/wz-app/dist/index.html index bcfe7f8..311f124 100644 --- a/new/wz-app/dist/index.html +++ b/new/wz-app/dist/index.html @@ -11,8 +11,8 @@ rel="stylesheet" /> 玩值电竞 - WanZhi Esports - - + +
diff --git a/new/wz-app/src/App.tsx b/new/wz-app/src/App.tsx index f71839f..f11577e 100644 --- a/new/wz-app/src/App.tsx +++ b/new/wz-app/src/App.tsx @@ -12,6 +12,7 @@ import { MallPointsPage } from "@/pages/MallPointsPage" import { ProfilePage } from "@/pages/ProfilePage" import { NotFoundPage } from "@/pages/NotFoundPage" import { LivePage } from "@/pages/LivePage" +import { AuthSessionListener } from "@/components/auth/AuthSessionListener" /** 带底栏 Tab 的主区(与全屏直播页互斥,避免底栏与输入条叠层) */ function TabLayout() { @@ -26,6 +27,7 @@ export default function App() { return ( + } /> { + const onLost = () => { + void (async () => { + await logout() + if (window.location.pathname !== "/login") { + navigate("/login", { replace: true }) + } + })() + } + window.addEventListener("wz:auth-lost", onLost) + return () => window.removeEventListener("wz:auth-lost", onLost) + }, [logout, navigate]) + + return null +} diff --git a/new/wz-app/src/lib/request.ts b/new/wz-app/src/lib/request.ts index 0b7f713..50050e0 100644 --- a/new/wz-app/src/lib/request.ts +++ b/new/wz-app/src/lib/request.ts @@ -60,6 +60,11 @@ export async function request(path: string, options: RequestOptions if (res.status === 401) { clearToken() + try { + window.dispatchEvent(new CustomEvent("wz:auth-lost")) + } catch { + /* ignore */ + } throw new Error(typeof json.message === "string" ? json.message : "未登录") } if (!res.ok) { diff --git a/new/wz-app/src/pages/LoginPage.tsx b/new/wz-app/src/pages/LoginPage.tsx index 7513dbf..a2906df 100644 --- a/new/wz-app/src/pages/LoginPage.tsx +++ b/new/wz-app/src/pages/LoginPage.tsx @@ -1,4 +1,4 @@ -import { useState } from "react" +import { useState, useEffect } from "react" import { useNavigate } from "react-router-dom" import { Button } from "@/components/ui/button" import { Input } from "@/components/ui/input" @@ -10,7 +10,7 @@ import { setToken } from "@/lib/token" export function LoginPage() { const navigate = useNavigate() - const { login, syncFromDatabase } = useAppContext() + const { login, syncFromDatabase, isLoggedIn, authChecked } = useAppContext() const [phone, setPhone] = useState("") const [name, setName] = useState("") const [password, setPassword] = useState("") @@ -20,6 +20,12 @@ export function LoginPage() { const [agreed, setAgreed] = useState(false) const [error, setError] = useState("") + useEffect(() => { + if (authChecked && isLoggedIn) { + navigate("/", { replace: true }) + } + }, [authChecked, isLoggedIn, navigate]) + const handleSubmit = async () => { if (!agreed) { setError("请先阅读并同意用户协议与隐私政策") @@ -188,12 +194,15 @@ export function LoginPage() { 其他登录方式
-
+

以下方式需微信开放平台等配置,暂不可用

+
{["微信", "QQ", "微博"].map((n) => ( diff --git a/new/wz-app/src/pages/ProfilePage.tsx b/new/wz-app/src/pages/ProfilePage.tsx index e3e7e6e..2595620 100644 --- a/new/wz-app/src/pages/ProfilePage.tsx +++ b/new/wz-app/src/pages/ProfilePage.tsx @@ -22,6 +22,11 @@ import { Button } from "@/components/ui/button" import { useAppContext } from "@/components/providers/app-provider" import { useState } from "react" +function maskPhone(p?: string): string { + if (!p || p.length < 7) return p || "—" + return `${p.slice(0, 3)}****${p.slice(-4)}` +} + export function ProfilePage() { const { user, wallet, logout } = useAppContext() const navigate = useNavigate() @@ -100,7 +105,7 @@ export function ProfilePage() {

- ID: {user.odlId || "888888"} + ID: {user.id || user.odlId || "—"} · {user.phone ? maskPhone(user.phone) : "手机未绑定"}

电竞达人 | 王者荣耀主播