account-register.tsx 7.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177
  1. import { CirclePlay, Send } from "lucide-react";
  2. import { useState } from "react";
  3. import { getRandomAccountApi, registerAccountApi } from "../../api/register";
  4. import { loginAccountApi } from "../../api/login";
  5. import { useAtomValue, useSetAtom } from "jotai";
  6. import { modalStackAtom, openModalAction } from "../../store";
  7. import { pmBridge } from "../../lib/PostMessageBridge";
  8. export interface AccountRegisterProps {
  9. switchPhoneRegister: () => void;
  10. switchLogin: () => void;
  11. }
  12. export const AccountRegister = ({ switchPhoneRegister, switchLogin }: AccountRegisterProps) => {
  13. const [userName, setUserName] = useState('');
  14. const [userPwd, setUserPwd] = useState('');
  15. const [loading, setLoading] = useState(false);
  16. const [agreed, setAgreed] = useState(false);
  17. const modalState = useAtomValue(modalStackAtom);
  18. const openModal = useSetAtom(openModalAction);
  19. const handleRandomAccount = async () => {
  20. setLoading(true);
  21. try {
  22. const res = await getRandomAccountApi({ is_activate: 1 });
  23. if (res.user_name && res.user_pwd) {
  24. setUserName(res.user_name);
  25. setUserPwd(res.user_pwd);
  26. }
  27. } catch (error: any) {
  28. console.error('获取随机账号失败:', error);
  29. alert(error.message || '获取随机账号失败');
  30. } finally {
  31. setLoading(false);
  32. }
  33. };
  34. const handleRegister = async () => {
  35. if (!userName) {
  36. alert('请输入账号');
  37. return;
  38. }
  39. if (!userPwd) {
  40. alert('请输入密码');
  41. return;
  42. }
  43. if (!agreed) {
  44. alert('请先同意服务协议与隐私权政策');
  45. return;
  46. }
  47. setLoading(true);
  48. try {
  49. // 首先执行注册
  50. await registerAccountApi({
  51. user_name: userName,
  52. user_pwd: userPwd
  53. });
  54. // 注册成功后立即执行登录
  55. const loginRes = await loginAccountApi({
  56. user_name: userName,
  57. user_pwd: userPwd
  58. });
  59. if (loginRes.token) {
  60. // 存储 token
  61. localStorage.setItem('token', loginRes.token);
  62. // 使用 pmBridge 回传给父 iframe
  63. const requestId = modalState.login.requestId;
  64. pmBridge.sendToIframe("LOGIN_SUCCESS", {success:true, data: loginRes}, requestId);
  65. // 关闭登录弹窗
  66. openModal({ name: 'login', item: { isOpen: false } });
  67. } else {
  68. alert('登录失败:未返回 token');
  69. }
  70. } catch (error: any) {
  71. console.error('流程失败:', error);
  72. alert(error.message || '操作失败');
  73. } finally {
  74. setLoading(false);
  75. }
  76. };
  77. return (
  78. <div className="fixed inset-0 z-[100] flex items-center justify-center bg-black/60 backdrop-blur-sm">
  79. <div className="w-full max-w-[320px] mx-5 bg-[#f5f7f8] rounded-2xl shadow-2xl overflow-hidden flex flex-col scale-100">
  80. <div className="flex flex-col items-center pt-4 pb-6 px-6">
  81. <h1 className="text-xl font-bold text-slate-900 dark:text-slate-100">创建账号</h1>
  82. </div>
  83. {/* Tabs */}
  84. <div className="flex border-b border-slate-200 dark:border-slate-800 px-6 gap-8">
  85. <button onClick={switchPhoneRegister} className="flex flex-col items-center justify-center border-b-[3px] border-transparent text-[#64748b] pb-3 pt-2 hover:text-primary transition-colors">
  86. <p className="text-sm font-bold leading-normal tracking-wide">手机号注册</p>
  87. </button>
  88. <button className="flex flex-col items-center justify-center border-b-[3px] border-primary text-primary pb-3 pt-2">
  89. <p className="text-sm font-bold leading-normal tracking-wide">账号注册</p>
  90. </button>
  91. </div>
  92. {/* Form Content */}
  93. <div className="p-6 space-y-4">
  94. {/* Account Input */}
  95. <label className="text-xs font-semibold uppercase tracking-wider text-slate-400 ml-1">账号</label>
  96. <div className="flex gap-2">
  97. <div className="flex-1">
  98. <input
  99. className="p-2 form-input input-field w-full rounded-lg border-slate-200 bg-white text-slate-900 h-12 text-sm"
  100. placeholder="请输入账号"
  101. type="text"
  102. value={userName}
  103. onChange={(e) => setUserName(e.target.value)}
  104. />
  105. </div>
  106. </div>
  107. {/* Password Input */}
  108. <label className="text-xs font-semibold uppercase tracking-wider text-slate-400 ml-1">密码</label>
  109. <div className="flex gap-2">
  110. <div className="flex-1">
  111. <input
  112. className="p-2 form-input input-field w-full rounded-lg border-slate-200 bg-white text-slate-900 h-12 text-sm"
  113. placeholder="请输入密码"
  114. type="text"
  115. value={userPwd}
  116. onChange={(e) => setUserPwd(e.target.value)}
  117. />
  118. </div>
  119. </div>
  120. <div className="flex justify-between items-center px-1">
  121. <a className="text-xs text-slate-500 dark:text-slate-400 hover:text-primary transition-colors cursor-pointer" onClick={switchLogin}>已有账号</a>
  122. <a className="text-xs text-slate-500 dark:text-slate-400 hover:text-primary transition-colors" href="#">遇到问题?</a>
  123. </div>
  124. {/* Action Button */}
  125. <button
  126. onClick={handleRegister}
  127. disabled={loading}
  128. className={`w-full bg-primary hover:bg-primary/90 text-white font-bold h-12 rounded-lg shadow-lg transition-all flex items-center justify-center gap-2 ${loading ? 'opacity-70 cursor-not-allowed' : ''}`}
  129. >
  130. {loading ? '注册中...' : '立即注册并进入游戏'} <CirclePlay size={18} />
  131. </button>
  132. <button
  133. onClick={handleRandomAccount}
  134. disabled={loading}
  135. className="w-full text-primary font-bold h-12 rounded-lg shadow-lg transition-all flex items-center justify-center gap-2 border border-primary/20 hover:bg-primary/5"
  136. >
  137. <Send size={18} />一键生成账号密码
  138. </button>
  139. {/* Secondary Links */}
  140. <div className="flex items-center gap-2 px-1 pt-2">
  141. <input
  142. className="h-4 w-4 rounded border-slate-300 text-primary focus:ring-primary cursor-pointer"
  143. id="tos"
  144. type="checkbox"
  145. checked={agreed}
  146. onChange={(e) => setAgreed(e.target.checked)}
  147. />
  148. <label htmlFor="tos" className="text-xs leading-relaxed text-slate-500 cursor-pointer select-none">
  149. 我已阅读并同意 <a className="text-primary hover:underline" href="#">服务协议</a> 与 <a className="text-primary hover:underline" href="#">隐私权政策</a>
  150. </label>
  151. </div>
  152. </div>
  153. </div>
  154. </div>
  155. );
  156. }