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.

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