feat(service-party-app): 验证成功后自动加入会话
- 移除手动输入名称和点击"确认加入"按钮的步骤 - 验证邀请码成功后自动触发 joinSession - 生成默认参与者名称(参与者-xxxx 格式) - 保留错误处理和重试功能 - 减少用户操作步骤,提高 co_managed_keygen 可靠性 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
parent
bd6537a2cb
commit
e72f96da10
|
|
@ -12,6 +12,12 @@ interface SessionInfo {
|
||||||
totalParticipants?: number;
|
totalParticipants?: number;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 生成默认参与者名称
|
||||||
|
function generateParticipantName(): string {
|
||||||
|
const timestamp = Date.now().toString(36).slice(-4);
|
||||||
|
return `参与者-${timestamp}`;
|
||||||
|
}
|
||||||
|
|
||||||
interface ValidateResult {
|
interface ValidateResult {
|
||||||
success: boolean;
|
success: boolean;
|
||||||
error?: string;
|
error?: string;
|
||||||
|
|
@ -24,13 +30,14 @@ export default function Join() {
|
||||||
const navigate = useNavigate();
|
const navigate = useNavigate();
|
||||||
|
|
||||||
const [code, setCode] = useState(inviteCode || '');
|
const [code, setCode] = useState(inviteCode || '');
|
||||||
const [participantName, setParticipantName] = useState('');
|
const [participantName] = useState(generateParticipantName());
|
||||||
const [isLoading, setIsLoading] = useState(false);
|
const [isLoading, setIsLoading] = useState(false);
|
||||||
const [error, setError] = useState<string | null>(null);
|
const [error, setError] = useState<string | null>(null);
|
||||||
const [sessionInfo, setSessionInfo] = useState<SessionInfo | null>(null);
|
const [sessionInfo, setSessionInfo] = useState<SessionInfo | null>(null);
|
||||||
const [joinToken, setJoinToken] = useState<string | null>(null);
|
const [joinToken, setJoinToken] = useState<string | null>(null);
|
||||||
const [partyId, setPartyId] = useState<string | null>(null);
|
const [partyId, setPartyId] = useState<string | null>(null);
|
||||||
const [step, setStep] = useState<'input' | 'confirm' | 'joining'>('input');
|
const [step, setStep] = useState<'input' | 'confirm' | 'joining'>('input');
|
||||||
|
const [autoJoinAttempted, setAutoJoinAttempted] = useState(false);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (inviteCode) {
|
if (inviteCode) {
|
||||||
|
|
@ -38,6 +45,22 @@ export default function Join() {
|
||||||
}
|
}
|
||||||
}, [inviteCode]);
|
}, [inviteCode]);
|
||||||
|
|
||||||
|
// 自动加入:验证成功后自动加入会话
|
||||||
|
useEffect(() => {
|
||||||
|
if (
|
||||||
|
step === 'confirm' &&
|
||||||
|
sessionInfo &&
|
||||||
|
joinToken &&
|
||||||
|
partyId &&
|
||||||
|
participantName &&
|
||||||
|
!autoJoinAttempted &&
|
||||||
|
!isLoading
|
||||||
|
) {
|
||||||
|
setAutoJoinAttempted(true);
|
||||||
|
handleJoinSession();
|
||||||
|
}
|
||||||
|
}, [step, sessionInfo, joinToken, partyId, participantName, autoJoinAttempted, isLoading]);
|
||||||
|
|
||||||
const handleValidateCode = async (codeToValidate: string) => {
|
const handleValidateCode = async (codeToValidate: string) => {
|
||||||
if (!codeToValidate.trim()) {
|
if (!codeToValidate.trim()) {
|
||||||
setError('请输入邀请码');
|
setError('请输入邀请码');
|
||||||
|
|
@ -76,8 +99,8 @@ export default function Join() {
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleJoinSession = async () => {
|
const handleJoinSession = async () => {
|
||||||
if (!sessionInfo || !participantName.trim()) {
|
if (!sessionInfo) {
|
||||||
setError('请输入参与者名称');
|
setError('会话信息不完整');
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -204,42 +227,42 @@ export default function Join() {
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className={styles.inputGroup}>
|
{error ? (
|
||||||
<label className={styles.label}>您的名称</label>
|
<>
|
||||||
<input
|
<div className={styles.error}>{error}</div>
|
||||||
type="text"
|
<div className={styles.actions}>
|
||||||
value={participantName}
|
<button
|
||||||
onChange={(e) => setParticipantName(e.target.value)}
|
className={styles.secondaryButton}
|
||||||
placeholder="输入您的名称(其他参与者可见)"
|
onClick={() => {
|
||||||
className={styles.input}
|
setStep('input');
|
||||||
disabled={isLoading}
|
setSessionInfo(null);
|
||||||
/>
|
setJoinToken(null);
|
||||||
</div>
|
setPartyId(null);
|
||||||
|
setError(null);
|
||||||
{error && <div className={styles.error}>{error}</div>}
|
setAutoJoinAttempted(false);
|
||||||
|
}}
|
||||||
<div className={styles.actions}>
|
disabled={isLoading}
|
||||||
<button
|
>
|
||||||
className={styles.secondaryButton}
|
返回
|
||||||
onClick={() => {
|
</button>
|
||||||
setStep('input');
|
<button
|
||||||
setSessionInfo(null);
|
className={styles.primaryButton}
|
||||||
setJoinToken(null);
|
onClick={() => {
|
||||||
setPartyId(null);
|
setAutoJoinAttempted(false);
|
||||||
setError(null);
|
setError(null);
|
||||||
}}
|
}}
|
||||||
disabled={isLoading}
|
disabled={isLoading}
|
||||||
>
|
>
|
||||||
返回
|
重试
|
||||||
</button>
|
</button>
|
||||||
<button
|
</div>
|
||||||
className={styles.primaryButton}
|
</>
|
||||||
onClick={handleJoinSession}
|
) : (
|
||||||
disabled={isLoading || !participantName.trim()}
|
<div className={styles.joining}>
|
||||||
>
|
<div className={styles.spinner}></div>
|
||||||
{isLoading ? '加入中...' : '确认加入'}
|
<p>正在自动加入会话...</p>
|
||||||
</button>
|
</div>
|
||||||
</div>
|
)}
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue