You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

1186 lines
25 KiB

4 weeks ago
4 weeks ago
1 month ago
  1. <template>
  2. <view class="login-registration-container">
  3. <!-- 自定义导航栏 -->
  4. <view
  5. class="custom-navbar"
  6. :style="{ paddingTop: safeAreaInsets?.top + 'px' }"
  7. >
  8. <!-- <view class="nav-left">
  9. <text class="back-btn" @click="goToIndex"></text>
  10. </view> -->
  11. <view class="nav-right">
  12. <image
  13. class="icons"
  14. src="../../../static/icons/Headset.png"
  15. alt="联系客服"
  16. />
  17. <image
  18. class="icons"
  19. @click="goToIndex"
  20. src="../../../static/icons/Frame.png"
  21. alt="返回首页"
  22. />
  23. </view>
  24. </view>
  25. <!-- Logo -->
  26. <!-- <image class="logo" src="/static/logo.png" mode="aspectFit"></image> -->
  27. <!-- 欢迎语 -->
  28. <text class="welcome-text">登录DeepChart</text>
  29. <!-- 邮箱/手机号切换 -->
  30. <view class="switch-container">
  31. <text
  32. class="switch-item"
  33. :class="{ active: switchType === 'User' }"
  34. @click="switchUser"
  35. >用户名</text
  36. >
  37. <text
  38. class="switch-item"
  39. :class="{ active: switchType === 'Phone' }"
  40. @click="switchPhone"
  41. >手机号</text
  42. ><text
  43. class="switch-item"
  44. :class="{ active: switchType === 'Email' }"
  45. @click="switchEmail"
  46. >邮箱</text
  47. >
  48. </view>
  49. <!-- 输入框 -->
  50. <view class="input-container">
  51. <view v-if="switchType === 'User'">
  52. <!-- 修改邮箱输入框容器将图标包含在内 -->
  53. <view class="input-with-icon">
  54. <image
  55. class="input-icon"
  56. src="../../../static/icons/People-safe.png"
  57. alt=""
  58. />
  59. <input
  60. class="input-field"
  61. type="text"
  62. placeholder="请输入DeepChart ID"
  63. v-model="deepChartID"
  64. />
  65. </view>
  66. <view class="input-with-icon">
  67. <image
  68. class="input-icon"
  69. src="../../../static/icons/Unlock.png"
  70. alt=""
  71. />
  72. <input
  73. class="input-field"
  74. type="text"
  75. placeholder="请输入密码"
  76. v-model="password"
  77. />
  78. </view>
  79. </view>
  80. <view v-if="switchType === 'Email'">
  81. <!-- 修改邮箱输入框容器将图标包含在内 -->
  82. <view class="input-with-icon">
  83. <image
  84. class="input-icon"
  85. src="../../../static/icons/Mail.png"
  86. alt=""
  87. />
  88. <input
  89. class="input-field"
  90. type="text"
  91. placeholder="请输入邮箱"
  92. v-model="email"
  93. />
  94. <view>
  95. <button
  96. class="send-code-btn-email"
  97. :disabled="isCodeBtnDisabled"
  98. :class="{ 'send-code-btn-disabled': isCodeBtnDisabled }"
  99. @click="sendCode"
  100. >
  101. <text
  102. class="send-code-text"
  103. :class="{ 'send-code-btn-disabled-text': isCodeBtnDisabled }"
  104. >{{ codeBtnText }}</text
  105. >
  106. </button>
  107. </view>
  108. </view>
  109. <view class="input-with-icon">
  110. <image
  111. class="input-icon"
  112. src="../../../static/icons/Text-recognition.png"
  113. alt=""
  114. />
  115. <input
  116. class="input-field"
  117. type="text"
  118. placeholder="请输入验证码"
  119. v-model="verifyCode"
  120. />
  121. </view>
  122. </view>
  123. <view v-if="switchType === 'Phone'" class="phone-input-container">
  124. <view class="country-code-selector" @click="showCountryPicker">
  125. <image
  126. class="country-flag-img"
  127. src="../../../static/icons/Iphone.png"
  128. mode="aspectFit"
  129. ></image>
  130. <text class="country-code">{{ selectedCountry.code }}</text>
  131. <!-- <text class="arrow-down"></text> -->
  132. </view>
  133. <input
  134. class="input-field phone-input"
  135. type="number"
  136. placeholder="输入手机号"
  137. v-model="phone"
  138. @input="onPhoneInput"
  139. />
  140. <view>
  141. <button
  142. class="send-code-btn"
  143. :disabled="isCodeBtnDisabled"
  144. :class="{ 'send-code-btn-disabled': isCodeBtnDisabled }"
  145. @click="sendCode"
  146. >
  147. <text
  148. class="send-code-text"
  149. :class="{ 'send-code-btn-disabled-text': isCodeBtnDisabled }"
  150. >{{ codeBtnText }}</text
  151. >
  152. </button>
  153. </view>
  154. </view>
  155. <view v-if="switchType === 'Phone'" class="input-with-icon">
  156. <image
  157. class="input-icon"
  158. src="../../../static/icons/Text-recognition.png"
  159. alt=""
  160. />
  161. <input
  162. class="input-field"
  163. type="text"
  164. placeholder="请输入验证码"
  165. v-model="verifyCode"
  166. />
  167. </view>
  168. </view>
  169. <!-- 用户协议 -->
  170. <view @click="changeCheckbox" class="agreement-container-one">
  171. <image class="checkbox" :src="checkboxUrl"></image>
  172. <text class="agreement-text-one"
  173. >接受 <text class="link" @click="openAgreement">用户协议</text>
  174. <text class="link" @click="openPrivacy">隐私政策</text></text
  175. >
  176. </view>
  177. <view v-if="switchType === 'User'" class="agreement-container">
  178. <text class="agreement-text"
  179. ><text @click="recoverPassword">忘记ID/密码</text>
  180. </text>
  181. </view>
  182. <view v-else class="agreement-container">
  183. <text class="agreement-text">
  184. <!-- 添加占位元素防止页面变形 -->
  185. <text style="visibility: hidden">占位符</text>
  186. </text>
  187. </view>
  188. <!-- 注册按钮 -->
  189. <button class="register-btn" @click="Login">
  190. <text v-if="!isLoading">登录</text>
  191. <image
  192. v-else
  193. class="icons-rotation"
  194. src="../../../static/icons/loading.png"
  195. ></image>
  196. </button>
  197. <!-- 或者 -->
  198. <text class="or-text" @click="goToRegistration"
  199. >如果您还没有账号点击注册
  200. <image class="to-icon" src="../../../static/icons/To.png"></image>
  201. </text>
  202. <!-- 第三方登录 -->
  203. <view class="third-party-login">
  204. <view class="third-party-btn" @click="loginWithApple">
  205. <image
  206. class="apple-icon"
  207. src="../../../static/icons/appleIcons.png"
  208. mode="aspectFit"
  209. ></image>
  210. <text class="third-party-text">通过 Apple 登录 </text>
  211. </view>
  212. <view class="third-party-btn" @click="loginWithGoogle">
  213. <image
  214. class="google-icon"
  215. src="../../../static/icons/GoogleIcons.png"
  216. mode="aspectFit"
  217. ></image>
  218. <text class="third-party-text">通过 Google 登录</text>
  219. </view>
  220. </view>
  221. <!-- 同意弹窗 -->
  222. <uniPopup ref="agreementPopup" type="dialog">
  223. <view class="popup-content">
  224. <text class="popup-message"
  225. >请阅读并同意<text @click="openAgreement" class="popup-message-link"
  226. >服务协议</text
  227. ><text @click="openPrivacy" class="popup-message-link"
  228. >隐私权限</text
  229. >
  230. </text>
  231. <view class="button-group">
  232. <button class="cancel-button" @click="handleCancel">
  233. <text class="cancel-text">取消</text>
  234. </button>
  235. <button class="agree-button" @click="handleAgree">
  236. <text class="agree-text">同意</text>
  237. </button>
  238. </view>
  239. </view>
  240. </uniPopup>
  241. <footerBar class="static-footer" :type="type"></footerBar>
  242. </view>
  243. </template>
  244. <script setup>
  245. import { ref } from "vue";
  246. // 导入完整的国家列表
  247. import countryList from "./list.js";
  248. import footerBar from "../../../components/footerBar";
  249. import uniPopupDialogVue from "../../../uni_modules/uni-popup/components/uni-popup-dialog/uni-popup-dialog.vue";
  250. import uniPopup from "../../../uni_modules/uni-popup/components/uni-popup/uni-popup.vue";
  251. import { verificationPhone, verificationEmail } from "../login/verification";
  252. import {
  253. LoginApi,
  254. SendEmailCodeApi,
  255. SendPhoneCodeApi,
  256. } from "../../../api/start/login";
  257. import { useUserStore } from "../../../stores/modules/userInfo";
  258. const deepChartID = ref("");
  259. const type = ref("member");
  260. const email = ref("");
  261. const password = ref("");
  262. const country = ref("+86");
  263. const phone = ref("");
  264. const agreed = ref(false);
  265. const switchType = ref("User"); // 默认是邮箱注册
  266. const { safeAreaInsets } = uni.getSystemInfoSync();
  267. const codeBtnText = ref("获取验证码");
  268. const isCodeBtnDisabled = ref(false); // 添加验证码按钮禁用状态
  269. const checkboxUrl = ref("../../../static/icons/Check-one-false.png");
  270. const verifyCode = ref("");
  271. const account = ref("");
  272. const isLoading = ref(false);
  273. // 使用从list.js导入的完整国家列表数据
  274. const countries = ref(
  275. countryList.list.map((item) => ({
  276. name: item.name,
  277. code: `+${item.tel}`,
  278. flag: item.flag,
  279. short: item.short,
  280. en: item.en,
  281. }))
  282. );
  283. // 默认选中的国家(中国)
  284. const selectedCountry = ref(
  285. countries.value.find((country) => country.short === "CN") ||
  286. countries.value[0]
  287. );
  288. // 显示国家选择器
  289. function showCountryPicker() {
  290. uni.showActionSheet({
  291. itemList: countries.value.map(
  292. (country) => `${country.name} ${country.code}`
  293. ),
  294. success: function (res) {
  295. selectedCountry.value = countries.value[res.tapIndex];
  296. country.value = selectedCountry.value.code;
  297. },
  298. });
  299. }
  300. function goToIndex() {
  301. // 返回上一页
  302. uni.navigateTo({
  303. url: "/pages/home/home",
  304. });
  305. }
  306. function switchUser() {
  307. // 切换到手机注册
  308. switchType.value = "User";
  309. password.value = "";
  310. verifyCode.value = "";
  311. }
  312. function switchEmail() {
  313. // 切换到邮箱注册
  314. switchType.value = "Email";
  315. password.value = "";
  316. verifyCode.value = "";
  317. }
  318. function switchPhone() {
  319. // 切换到手机注册
  320. switchType.value = "Phone";
  321. password.value = "";
  322. verifyCode.value = "";
  323. }
  324. // 登录
  325. async function Login() {
  326. if (!basicVerification()) {
  327. return;
  328. }
  329. const account = changeAccount();
  330. const loginType = changeLoginType();
  331. isLoading.value = true;
  332. const res = await LoginApi({
  333. loginType: loginType,
  334. account: account,
  335. verifyCode: verifyCode.value,
  336. password: password.value,
  337. useCode: verifyCode.value ? true : false,
  338. idToken: "",
  339. });
  340. isLoading.value = false;
  341. const message = res.message;
  342. if (res.code === 200) {
  343. // 登录成功
  344. uni.showToast({
  345. title: "登录成功",
  346. icon: "success",
  347. });
  348. const userStore = useUserStore();
  349. userStore.setUserInfo(res.data);
  350. console.log("userInfo为", userStore.userInfo);
  351. // 跳转到首页
  352. uni.redirectTo({
  353. url: "/pages/home/home",
  354. });
  355. } else {
  356. // 登录失败
  357. uni.showToast({
  358. title: message,
  359. icon: "none",
  360. });
  361. }
  362. }
  363. // 基础验证
  364. function basicVerification() {
  365. if (switchType.value === "User") {
  366. if (!deepChartID.value) {
  367. uni.showToast({
  368. title: "请输入用户名",
  369. icon: "none",
  370. });
  371. return false;
  372. }
  373. if (!password.value) {
  374. uni.showToast({
  375. title: "请输入密码",
  376. icon: "none",
  377. });
  378. return false;
  379. }
  380. }
  381. if (switchType.value === "Phone") {
  382. // 登录逻辑
  383. if (!phone.value) {
  384. uni.showToast({
  385. title: "请输入手机号码",
  386. icon: "none",
  387. });
  388. return false;
  389. }
  390. const phoneAll = `${country.value}${phone.value}`;
  391. console.log("完整手机号" + phoneAll);
  392. if (!validatePhoneNumber(country.value, phone.value)) {
  393. return false;
  394. }
  395. if (!verifyCode.value) {
  396. uni.showToast({
  397. title: "请输入验证码",
  398. icon: "none",
  399. });
  400. return false;
  401. }
  402. }
  403. if (switchType.value === "Email") {
  404. // 登录逻辑
  405. if (!email.value) {
  406. uni.showToast({
  407. title: "请输入邮箱地址",
  408. icon: "none",
  409. });
  410. return false;
  411. }
  412. const bool = verificationEmail(email.value);
  413. console.log("验证是否成功", bool);
  414. // 检查格式是否正确
  415. if (!bool) {
  416. uni.showToast({
  417. title: "邮箱格式不正确",
  418. icon: "none",
  419. });
  420. return false;
  421. }
  422. if (!verifyCode.value) {
  423. uni.showToast({
  424. title: "请输入验证码",
  425. icon: "none",
  426. });
  427. return false;
  428. }
  429. }
  430. if (!agreed.value) {
  431. // 显示同意弹窗
  432. agreementPopup.value.open();
  433. return;
  434. }
  435. return true;
  436. }
  437. // 注册码码验证
  438. function VerCodeVerfifcation() {
  439. if (switchType.value === "Phone") {
  440. if (!phone.value) {
  441. uni.showToast({
  442. title: "请输入手机号",
  443. icon: "none",
  444. });
  445. return false;
  446. }
  447. const bool = verificationPhone(country.value, phone.value);
  448. console.log("验证是否成功", bool);
  449. // 检查格式是否正确
  450. if (!bool) {
  451. uni.showToast({
  452. title: "手机号格式不正确",
  453. icon: "none",
  454. });
  455. return false;
  456. }
  457. }
  458. if (switchType.value === "Email") {
  459. if (!email.value) {
  460. uni.showToast({
  461. title: "请输入邮箱地址",
  462. icon: "none",
  463. });
  464. return false;
  465. }
  466. const bool = verificationEmail(email.value);
  467. console.log("验证是否成功", bool);
  468. // 检查格式是否正确
  469. if (!bool) {
  470. uni.showToast({
  471. title: "邮箱格式不正确",
  472. icon: "none",
  473. });
  474. return false;
  475. }
  476. }
  477. return true;
  478. }
  479. // 请求账户
  480. function changeAccount() {
  481. if (switchType.value === "User") {
  482. account.value = deepChartID.value;
  483. }
  484. if (switchType.value === "Phone") {
  485. account.value = `${country.value}${phone.value}`;
  486. }
  487. if (switchType.value === "Email") {
  488. account.value = email.value;
  489. }
  490. return account.value;
  491. }
  492. // 改变请求时的type
  493. function changeLoginType() {
  494. if (switchType.value === "User") {
  495. return "DCCODE";
  496. }
  497. if (switchType.value === "Phone") {
  498. return "PHONE";
  499. }
  500. if (switchType.value === "Email") {
  501. return "EMAIL";
  502. }
  503. }
  504. // 添加弹窗引用
  505. const agreementPopup = ref(null);
  506. // 处理同意按钮点击
  507. function handleAgree() {
  508. // 关闭弹窗
  509. agreementPopup.value.close();
  510. // 设置为已同意
  511. agreed.value = true;
  512. checkboxUrl.value = "../../../static/icons/Check-one-true.png";
  513. // 继续登录流程
  514. }
  515. // 处理同意按钮点击
  516. function handleCancel() {
  517. // 关闭弹窗
  518. agreementPopup.value.close();
  519. }
  520. // 苹果登录
  521. function loginWithApple() {
  522. // Apple登录逻辑
  523. console.log("通过Apple登录");
  524. uni.login({
  525. provider: "apple",
  526. success: function (loginRes) {
  527. // 登录成功
  528. uni.getUserInfo({
  529. provider: "apple",
  530. success: function (info) {
  531. console.log(info);
  532. },
  533. });
  534. },
  535. fail: function (err) {
  536. // 登录授权失败
  537. // err.code错误码参考`授权失败错误码(code)说明`
  538. console.log(err);
  539. },
  540. });
  541. }
  542. // 谷歌登录
  543. function loginWithGoogle() {
  544. // Google登录逻辑
  545. console.log("通过Google登录");
  546. uni.login({
  547. provider: "google",
  548. success: function (loginRes) {
  549. // 登录成功
  550. uni.getUserInfo({
  551. provider: "google",
  552. success: function (info) {
  553. console.log(info);
  554. },
  555. });
  556. },
  557. fail: function (err) {
  558. // 登录授权失败
  559. // err.code是错误码
  560. console.log(err);
  561. },
  562. });
  563. }
  564. function goToRegistration() {
  565. // 跳转到登录页
  566. uni.navigateTo({
  567. url: "/pages/start/Registration/Registration",
  568. });
  569. }
  570. function onPhoneInput(e) {
  571. // 确保只允许输入数字
  572. const value = e.detail.value;
  573. // 使用 isNaN 检查是否为有效数字
  574. if (isNaN(value)) {
  575. phone.value = "";
  576. } else {
  577. phone.value = value;
  578. }
  579. }
  580. // 发送验证码
  581. async function sendCode() {
  582. if (!VerCodeVerfifcation()) {
  583. return;
  584. }
  585. // 如果按钮已禁用,则不执行后续逻辑
  586. if (isCodeBtnDisabled.value) return;
  587. if (switchType.value === "Phone") {
  588. // 发送验证码
  589. const phoneAll = `${country.value}${phone.value}`;
  590. const res = await SendPhoneCodeApi({
  591. phone: phoneAll,
  592. });
  593. console.log("手机验证码:", res.message);
  594. if (!res) {
  595. uni.showToast({
  596. title: "请求失败",
  597. icon: "none",
  598. });
  599. }
  600. }
  601. if (switchType.value === "Email") {
  602. // 发送验证码
  603. const res = await SendEmailCodeApi({
  604. email: email.value,
  605. });
  606. console.log("邮箱验证码:", res.message);
  607. if (!res) {
  608. uni.showToast({
  609. title: "请求失败",
  610. icon: "none",
  611. });
  612. }
  613. }
  614. // 设置按钮为禁用状态
  615. isCodeBtnDisabled.value = true;
  616. codeBtnText.value = "重新发送";
  617. let time = 6;
  618. const timer = setInterval(() => {
  619. time--;
  620. codeBtnText.value = "重新发送 " + time + "s";
  621. if (time <= 0) {
  622. clearInterval(timer);
  623. codeBtnText.value = "重新发送";
  624. // 倒计时结束后启用按钮
  625. isCodeBtnDisabled.value = false;
  626. }
  627. }, 1000);
  628. return;
  629. }
  630. function openAgreement() {
  631. // 打开用户协议
  632. console.log("打开用户协议");
  633. uni.navigateTo({
  634. url: "/pages/start/agreement/agreement",
  635. });
  636. }
  637. function openPrivacy() {
  638. // 打开隐私政策
  639. console.log("打开隐私政策");
  640. uni.navigateTo({
  641. url: "/pages/start/privacy/privacy",
  642. });
  643. }
  644. function recoverPassword() {
  645. // 忘记密码
  646. // console.log("忘记密码");
  647. uni.navigateTo({
  648. url: "/pages/start/recoverPassword/recoverPassword",
  649. });
  650. }
  651. function changeCheckbox() {
  652. agreed.value = !agreed.value;
  653. checkboxUrl.value = agreed.value
  654. ? "../../../static/icons/Check-one-true.png"
  655. : "../../../static/icons/Check-one-false.png";
  656. }
  657. // 验证手机号是否正确
  658. function validatePhoneNumber(countryCode, phoneNumber) {
  659. // 检查是否为空
  660. if (!phoneNumber || phoneNumber.trim() === "") {
  661. uni.showToast({
  662. title: "手机号不能为空",
  663. icon: "none",
  664. });
  665. return false;
  666. }
  667. const bool = verificationPhone(countryCode, phoneNumber);
  668. console.log("验证是否成功", bool);
  669. // 检查格式是否正确
  670. if (!bool) {
  671. uni.showToast({
  672. title: "手机号格式不正确",
  673. icon: "none",
  674. });
  675. return false;
  676. }
  677. // 去掉+号后检查长度(手机号通常在7到15位之间)
  678. const cleanNumber = phoneNumber.replace(/^\+/, "");
  679. if (cleanNumber.length < 7 || cleanNumber.length > 15) {
  680. uni.showToast({
  681. title: "手机号长度不正确",
  682. icon: "none",
  683. });
  684. return false;
  685. }
  686. return true;
  687. }
  688. </script>
  689. <style scoped>
  690. .login-registration-container {
  691. display: flex;
  692. flex-direction: column;
  693. align-items: center;
  694. justify-content: center;
  695. padding: 0 70rpx;
  696. height: 100vh;
  697. background-color: #ffffff;
  698. }
  699. /* 自定义导航栏样式 */
  700. .custom-navbar {
  701. position: absolute;
  702. top: 0;
  703. left: 0;
  704. /* z-index: 999; */
  705. width: 90%;
  706. height: 80rpx;
  707. display: flex;
  708. justify-content: space-between;
  709. align-items: center;
  710. padding: 10rpx 40rpx;
  711. margin-bottom: 20rpx;
  712. }
  713. .nav-left,
  714. .nav-right {
  715. flex: 1;
  716. }
  717. .nav-right {
  718. display: flex;
  719. justify-content: flex-end;
  720. }
  721. .icons {
  722. margin: 20rpx;
  723. width: 40rpx;
  724. height: 40rpx;
  725. /* margin-right: 10rpx; */
  726. }
  727. .icons-rotation {
  728. margin: 20rpx;
  729. width: 40rpx;
  730. height: 40rpx;
  731. /* margin-right: 10rpx; */
  732. animation: rotation 2s linear infinite;
  733. }
  734. @keyframes rotation {
  735. from {
  736. transform: rotate(0deg);
  737. }
  738. to {
  739. transform: rotate(360deg);
  740. }
  741. }
  742. .back-btn,
  743. .headphone-btn {
  744. font-size: 36rpx;
  745. font-weight: bold;
  746. color: #333333;
  747. padding: 10rpx;
  748. }
  749. .logo {
  750. width: 120rpx;
  751. height: 120rpx;
  752. margin-bottom: 60rpx;
  753. border-radius: 20%;
  754. }
  755. .welcome-text {
  756. font-size: 48rpx;
  757. font-weight: bold;
  758. color: #333333;
  759. margin-bottom: 60rpx;
  760. /* text-align: left; */
  761. /* align-self: flex-start; */
  762. }
  763. .switch-container {
  764. display: flex;
  765. margin-bottom: 40rpx;
  766. align-self: flex-start;
  767. }
  768. .switch-item {
  769. font-size: 28rpx;
  770. color: #999999;
  771. padding: 10rpx 20rpx;
  772. position: relative;
  773. }
  774. .switch-item::after {
  775. content: "";
  776. position: absolute;
  777. bottom: 0;
  778. left: 50%;
  779. transform: translateX(-50%);
  780. width: 60%;
  781. /* 控制边框宽度 */
  782. height: 2rpx;
  783. background-color: transparent;
  784. }
  785. .switch-item.active {
  786. color: #333333;
  787. font-weight: 700;
  788. }
  789. .switch-item.active::after {
  790. content: "";
  791. position: absolute;
  792. top: 60rpx;
  793. bottom: 0;
  794. left: 50%;
  795. transform: translateX(-50%);
  796. width: 30%;
  797. /* 控制边框宽度 */
  798. height: 7rpx;
  799. background-color: #333333;
  800. }
  801. .input-container {
  802. width: 100%;
  803. }
  804. /* 添加图标输入框样式 */
  805. .input-with-icon {
  806. display: flex;
  807. align-items: center;
  808. width: 100%;
  809. height: 80rpx;
  810. border-bottom: 2rpx solid #e5e5e5;
  811. margin-bottom: 20rpx;
  812. }
  813. .input-icon {
  814. width: 40rpx;
  815. height: 40rpx;
  816. margin: 0 20rpx;
  817. }
  818. .input-field {
  819. flex: 1;
  820. height: 80rpx;
  821. padding: 15rpx 0;
  822. font-size: 28rpx;
  823. color: #333333;
  824. border: none;
  825. background-color: transparent;
  826. }
  827. .phone-input-container {
  828. display: flex;
  829. align-items: center;
  830. width: 95.8%;
  831. height: 80rpx;
  832. /* border-radius: 20rpx; */
  833. /* border: 2rpx solid #e5e5e5; */
  834. /* background-color: #f5f5f5; */
  835. padding: 0 10rpx;
  836. border-bottom: 2rpx solid #e5e5e5;
  837. margin-bottom: 20rpx;
  838. }
  839. .country-code-selector {
  840. display: flex;
  841. align-items: center;
  842. padding: 0 10rpx;
  843. padding-bottom: 1rpx;
  844. height: 100%;
  845. /* border-right: 2rpx solid #e5e5e5; */
  846. /* background-color: #f5f5f5; */
  847. border-radius: 20rpx 0 0 20rpx;
  848. }
  849. .country-code {
  850. font-size: 28rpx;
  851. color: #333333;
  852. margin-right: 10rpx;
  853. }
  854. .country-flag-img {
  855. width: 40rpx;
  856. height: 40rpx;
  857. margin-right: 10rpx;
  858. }
  859. .arrow-down {
  860. font-size: 20rpx;
  861. color: #999999;
  862. }
  863. .phone-input {
  864. flex: 1;
  865. width: auto;
  866. height: 100%;
  867. border: none;
  868. background-color: transparent;
  869. padding: 0 0rpx;
  870. }
  871. .send-code-btn {
  872. width: 200rpx;
  873. height: 60rpx;
  874. display: inline-flex;
  875. padding: 0rpx 10rpx;
  876. justify-content: center;
  877. align-items: center;
  878. gap: 10px;
  879. border-radius: 4px;
  880. background: #000;
  881. }
  882. .send-code-btn-email {
  883. width: 200rpx;
  884. height: 60rpx;
  885. display: inline-flex;
  886. padding: 0rpx 10rpx;
  887. justify-content: center;
  888. align-items: center;
  889. gap: 10px;
  890. border-radius: 4px;
  891. background: #000;
  892. margin-right: 15rpx;
  893. }
  894. .send-code-btn-disabled {
  895. background: #e6e6e6;
  896. /* 禁用状态下的灰色背景 */
  897. }
  898. .send-code-btn-disabled-text {
  899. color: #999999 !important;
  900. }
  901. .send-code-text {
  902. color: #fff;
  903. font-size: 28rpx;
  904. }
  905. .agreement-container-one {
  906. display: flex;
  907. align-items: center;
  908. align-self: flex-start;
  909. margin-bottom: 80rpx;
  910. }
  911. .agreement-container {
  912. display: flex;
  913. align-items: center;
  914. margin-bottom: 30rpx;
  915. margin-top: -60rpx;
  916. align-self: flex-start;
  917. }
  918. .checkbox {
  919. width: 30rpx;
  920. height: 30rpx;
  921. margin-left: 20rpx;
  922. /* flex: content; */
  923. }
  924. .agreement-text-one {
  925. font-size: 22rpx;
  926. color: #666666;
  927. text-align: center;
  928. margin-left: 10rpx;
  929. }
  930. .agreement-text {
  931. margin-left: 20rpx;
  932. font-size: 24rpx;
  933. color: #666666;
  934. white-space: nowrap;
  935. }
  936. .link {
  937. color: #333333;
  938. font-weight: bold;
  939. text-decoration: underline;
  940. }
  941. .register-btn {
  942. width: 100%;
  943. height: 80rpx;
  944. background-color: #000000;
  945. color: white;
  946. font-size: 32rpx;
  947. font-weight: bold;
  948. border-radius: 40rpx;
  949. margin-bottom: 40rpx;
  950. }
  951. .or-text {
  952. font-size: 24rpx;
  953. color: #999999;
  954. margin-bottom: 40rpx;
  955. }
  956. .to-icon {
  957. width: 10rpx;
  958. height: 16rpx;
  959. }
  960. .third-party-login {
  961. width: 100%;
  962. margin-bottom: 60rpx;
  963. }
  964. .third-party-text {
  965. color: #ffffff;
  966. font-weight: bold;
  967. white-space: pre;
  968. }
  969. .third-party-btn {
  970. width: 100%;
  971. height: 80rpx;
  972. background-color: rgb(0, 0, 0);
  973. border: 2rpx solid #e5e5e5;
  974. border-radius: 40rpx;
  975. display: flex;
  976. align-items: center;
  977. justify-content: center;
  978. margin-bottom: 20rpx;
  979. font-size: 28rpx;
  980. color: #333333;
  981. }
  982. .google-icon,
  983. .apple-icon {
  984. width: 60rpx;
  985. height: 60rpx;
  986. margin-right: 20rpx;
  987. }
  988. .existing-account {
  989. display: flex;
  990. align-items: center;
  991. }
  992. .account-text {
  993. font-size: 24rpx;
  994. color: #666666;
  995. }
  996. .login-link {
  997. font-size: 24rpx;
  998. font-weight: bold;
  999. color: #333333;
  1000. margin-left: 10rpx;
  1001. text-decoration: underline;
  1002. }
  1003. .static-footer {
  1004. position: fixed;
  1005. bottom: 0;
  1006. }
  1007. /* 弹窗样式 */
  1008. .popup-content {
  1009. background-color: #ffffff;
  1010. padding: 40rpx;
  1011. text-align: center;
  1012. border-radius: 10rpx;
  1013. width: 550rpx;
  1014. }
  1015. .popup-message {
  1016. font-size: 28rpx;
  1017. color: #000000;
  1018. margin-bottom: 60rpx;
  1019. margin-top: 20rpx;
  1020. text-align: center; /* 水平居中 */
  1021. display: flex; /* 使用flex布局 */
  1022. justify-content: center; /* 水平居中 */
  1023. align-items: center; /* 垂直居中 */
  1024. font-weight: 300;
  1025. }
  1026. .popup-message-link {
  1027. font-weight: 700;
  1028. }
  1029. .button-group {
  1030. display: flex;
  1031. justify-content: space-around;
  1032. }
  1033. .agree-button {
  1034. width: 160rpx;
  1035. height: 56rpx;
  1036. background-color: #000000;
  1037. border-radius: 40rpx;
  1038. display: flex; /* 添加flex布局 */
  1039. align-items: center; /* 垂直居中 */
  1040. justify-content: center; /* 水平居中 */
  1041. }
  1042. .agree-text {
  1043. color: #ffffff;
  1044. font-size: 34rpx;
  1045. /* 添加垂直居中相关样式 */
  1046. display: flex;
  1047. align-items: center;
  1048. justify-content: center;
  1049. line-height: 1; /* 确保文字垂直居中 */
  1050. }
  1051. .cancel-button {
  1052. width: 160rpx;
  1053. height: 56rpx;
  1054. background-color: #e5e5e5;
  1055. border-radius: 40rpx;
  1056. display: flex; /* 添加flex布局 */
  1057. align-items: center; /* 垂直居中 */
  1058. justify-content: center; /* 水平居中 */
  1059. }
  1060. .cancel-text {
  1061. color: #333333;
  1062. font-size: 34rpx;
  1063. /* 添加垂直居中相关样式 */
  1064. display: flex;
  1065. align-items: center;
  1066. justify-content: center;
  1067. line-height: 1; /* 确保文字垂直居中 */
  1068. }
  1069. </style>