imeeting/frontend/src/pages/business/PublicDeviceMeetingCreate.tsx

151 lines
5.0 KiB
TypeScript
Raw Normal View History

2026-06-05 07:07:45 +00:00
import { App, Button, Card, Result, Space, Spin, Typography } from "antd";
import { CheckCircleOutlined, QrcodeOutlined } from "@ant-design/icons";
import { useEffect, useState } from "react";
import { useNavigate, useParams } from "react-router-dom";
2026-06-05 07:07:45 +00:00
import { createPublicDeviceMeetingBySession } from "@/api/business/meeting";
const { Title, Text } = Typography;
export default function PublicDeviceMeetingCreate() {
const { message } = App.useApp();
const navigate = useNavigate();
const { sessionId } = useParams<{ sessionId: string }>();
2026-06-05 07:07:45 +00:00
const [ready, setReady] = useState(false);
const [submitting, setSubmitting] = useState(false);
2026-06-05 07:07:45 +00:00
const [confirmed, setConfirmed] = useState(false);
useEffect(() => {
const token = localStorage.getItem("accessToken");
if (!token) {
const redirect = encodeURIComponent(window.location.pathname + window.location.search);
navigate(`/login?redirect=${redirect}`, { replace: true });
return;
}
2026-06-05 07:07:45 +00:00
setReady(true);
}, [navigate]);
2026-06-05 07:07:45 +00:00
const handleConfirm = async () => {
if (!sessionId) {
message.error("扫码会话不存在");
return;
}
setSubmitting(true);
try {
2026-06-05 07:07:45 +00:00
await createPublicDeviceMeetingBySession(sessionId);
setConfirmed(true);
message.success("登录确认已发送到设备");
} catch {
2026-06-05 07:07:45 +00:00
message.error("登录确认失败");
} finally {
setSubmitting(false);
}
};
return (
2026-06-05 07:07:45 +00:00
<div
style={{
minHeight: "100vh",
background: "linear-gradient(180deg, #f7fbff 0%, #eef4f8 100%)",
padding: "48px 16px",
}}
>
<div style={{ maxWidth: 720, margin: "0 auto" }}>
<Card
style={{
borderRadius: 20,
boxShadow: "0 24px 64px rgba(15, 49, 86, 0.08)",
border: "1px solid #d9e6f2",
}}
>
{!ready ? (
<div style={{ padding: "64px 0", textAlign: "center" }}>
<Spin />
</div>
2026-06-05 07:07:45 +00:00
) : !sessionId ? (
<Result
status="error"
title="二维码参数无效"
subTitle="请返回设备端重新生成二维码后再扫码。"
extra={
<Button type="primary" onClick={() => navigate("/meetings")}>
</Button>
}
/>
) : confirmed ? (
<Result
status="success"
title="登录确认已发送"
subTitle="安卓设备收到确认消息后,会继续按离线发会流程创建会议。"
extra={
<Button type="primary" onClick={() => navigate("/meetings")}>
</Button>
}
/>
) : (
2026-06-05 07:07:45 +00:00
<Space direction="vertical" size={24} style={{ width: "100%" }}>
<Space size={16} align="start">
<div
style={{
width: 56,
height: 56,
borderRadius: 16,
background: "#e6f4ff",
display: "flex",
alignItems: "center",
justifyContent: "center",
color: "#1677ff",
fontSize: 24,
}}
>
<QrcodeOutlined />
</div>
<div>
<Title level={3} style={{ margin: 0 }}>
</Title>
<Text type="secondary">
H5
</Text>
</div>
</Space>
<Card
bordered={false}
style={{
background: "#f6fbff",
border: "1px solid #d7e8f6",
borderRadius: 16,
}}
>
<Space direction="vertical" size={12}>
<Text>
<CheckCircleOutlined style={{ color: "#1677ff", marginRight: 8 }} />
线
</Text>
<Text type="secondary">
访
</Text>
</Space>
</Card>
2026-06-05 07:07:45 +00:00
<div style={{ display: "flex", justifyContent: "flex-end" }}>
<Space>
2026-06-05 07:07:45 +00:00
<Button size="large" onClick={() => navigate(-1)}>
</Button>
<Button type="primary" size="large" loading={submitting} onClick={() => void handleConfirm()}>
</Button>
</Space>
</div>
2026-06-05 07:07:45 +00:00
</Space>
)}
</Card>
</div>
</div>
);
}