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.

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