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.

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