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.

1090 lines
24 KiB

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