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.

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