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.

1054 lines
22 KiB

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