比较提交

..

2 次代码提交

作者 SHA1 备注 提交日期
cryptocommuniums-afk
264d49475b Sync changelog with repo version 5c2dcf2 2026-03-15 18:05:45 +08:00
cryptocommuniums-afk
5c2dcf23ba Add leave-state hints for live analysis 2026-03-15 18:05:33 +08:00
修改 3 个文件,包含 96 行新增0 行删除

查看文件

@@ -8,6 +8,22 @@ export type ChangeLogEntry = {
};
export const CHANGE_LOG_ENTRIES: ChangeLogEntry[] = [
{
version: "2026.03.15-live-analysis-leave-hint",
releaseDate: "2026-03-15",
repoVersion: "5c2dcf2",
summary: "实时分析结束后增加离开提示,明确何时必须停留、何时可以安全关闭或切页。",
features: [
"分析进行中显示“不要关闭或切走页面”提示",
"结束分析后保存阶段显示“请暂时停留当前页面”提示",
"保存成功后明确提示“现在可以关闭浏览器或切换到其他页面”",
"分析中和保存中挂接 beforeunload 提醒,减少误关页面导致的数据丢失",
],
tests: [
"pnpm check",
"pnpm build",
],
},
{
version: "2026.03.15-training-generator-collapse",
releaseDate: "2026-03-15",

查看文件

@@ -1,5 +1,6 @@
import { useAuth } from "@/_core/hooks/useAuth";
import { trpc } from "@/lib/trpc";
import { Alert, AlertDescription, AlertTitle } from "@/components/ui/alert";
import { Badge } from "@/components/ui/badge";
import { Button } from "@/components/ui/button";
import { Card, CardContent, CardDescription, CardHeader, CardTitle } from "@/components/ui/card";
@@ -572,6 +573,7 @@ export default function LiveCamera() {
const [sessionMode, setSessionMode] = useState<SessionMode>("practice");
const [analyzing, setAnalyzing] = useState(false);
const [saving, setSaving] = useState(false);
const [leaveStatus, setLeaveStatus] = useState<"idle" | "analyzing" | "saving" | "safe" | "failed">("idle");
const [immersivePreview, setImmersivePreview] = useState(false);
const [liveScore, setLiveScore] = useState<PoseScore | null>(null);
const [currentAction, setCurrentAction] = useState<ActionType>("unknown");
@@ -979,6 +981,7 @@ export default function LiveCamera() {
analyzingRef.current = true;
setAnalyzing(true);
setSaving(false);
setLeaveStatus("analyzing");
setSegments([]);
segmentsRef.current = [];
currentSegmentRef.current = null;
@@ -1049,6 +1052,7 @@ export default function LiveCamera() {
} catch (error: any) {
analyzingRef.current = false;
setAnalyzing(false);
setLeaveStatus("idle");
await stopSessionRecorder();
toast.error(`实时分析启动失败: ${error?.message || "未知错误"}`);
}
@@ -1059,6 +1063,7 @@ export default function LiveCamera() {
analyzingRef.current = false;
setAnalyzing(false);
setSaving(true);
setLeaveStatus("saving");
if (animationRef.current) {
cancelAnimationFrame(animationRef.current);
@@ -1071,15 +1076,32 @@ export default function LiveCamera() {
poseRef.current = null;
}
await persistSession();
setLeaveStatus("safe");
toast.success("实时分析已保存,并同步写入训练记录");
await liveSessionsQuery.refetch();
} catch (error: any) {
setLeaveStatus("failed");
toast.error(`保存实时分析失败: ${error?.message || "未知错误"}`);
} finally {
setSaving(false);
}
}, [liveSessionsQuery, persistSession]);
useEffect(() => {
if (!analyzing && !saving) {
return;
}
const handleBeforeUnload = (event: BeforeUnloadEvent) => {
event.preventDefault();
event.returnValue = "实时分析数据仍在处理中,请先等待保存完成。";
return event.returnValue;
};
window.addEventListener("beforeunload", handleBeforeUnload);
return () => window.removeEventListener("beforeunload", handleBeforeUnload);
}, [analyzing, saving]);
const handleSetupComplete = useCallback(async () => {
setShowSetupGuide(false);
await startCamera(facing, zoomTargetRef.current, qualityPreset);
@@ -1217,6 +1239,46 @@ export default function LiveCamera() {
</DialogContent>
</Dialog>
{leaveStatus === "analyzing" ? (
<Alert>
<Activity className="h-4 w-4" />
<AlertTitle></AlertTitle>
<AlertDescription>
</AlertDescription>
</Alert>
) : null}
{leaveStatus === "saving" ? (
<Alert>
<Activity className="h-4 w-4" />
<AlertTitle></AlertTitle>
<AlertDescription>
</AlertDescription>
</Alert>
) : null}
{leaveStatus === "safe" ? (
<Alert>
<CheckCircle2 className="h-4 w-4" />
<AlertTitle></AlertTitle>
<AlertDescription>
</AlertDescription>
</Alert>
) : null}
{leaveStatus === "failed" ? (
<Alert>
<Activity className="h-4 w-4" />
<AlertTitle></AlertTitle>
<AlertDescription>
</AlertDescription>
</Alert>
) : null}
<section className="rounded-[28px] border border-border/60 bg-[radial-gradient(circle_at_top_left,_rgba(249,115,22,0.16),_transparent_32%),linear-gradient(135deg,rgba(12,18,24,0.98),rgba(26,31,43,0.96))] p-5 text-white shadow-xl shadow-black/10 md:p-7">
<div className="flex flex-col gap-4 lg:flex-row lg:items-end lg:justify-between">
<div className="space-y-3">

查看文件

@@ -1,5 +1,23 @@
# Tennis Training Hub - 变更日志
## 2026.03.15-live-analysis-leave-hint (2026-03-15)
### 功能更新
- 实时分析进行中显示“不要关闭浏览器或切走页面”提示
- 点击“结束分析”后,保存阶段显示“请暂时停留当前页面”提示
- 保存完成后明确提示“现在可以关闭浏览器或切换到其他页面”
- 分析中和保存中增加离开页面提醒,减少误关导致的数据丢失
### 测试
- `pnpm check`
- `pnpm build`
### 仓库版本
- `5c2dcf2`
## 2026.03.15-training-generator-collapse (2026-03-15)
### 功能更新