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.

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