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.

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