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.

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