phone.uvue 2.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134
  1. <template>
  2. <view class="flex flex-col mb-5">
  3. <cl-text :pt="{ className: 'text-lg font-bold' }">{{ t("手机登录") }}</cl-text>
  4. <cl-text :pt="{ className: 'text-sm mt-2' }" color="info">{{
  5. t("未注册的手机号登录成功后将自动注册")
  6. }}</cl-text>
  7. </view>
  8. <view class="flex flex-col">
  9. <view class="mb-3 flex flex-row">
  10. <cl-input
  11. v-model="form.phone"
  12. prefix-icon="device-fill"
  13. :placeholder="t('请输入手机号')"
  14. :border="false"
  15. :pt="{
  16. className: parseClass([
  17. '!h-[90rpx] flex-1 !rounded-xl !px-4',
  18. [isDark, '!bg-surface-70', '!bg-white']
  19. ]),
  20. prefixIcon: {
  21. className: 'mr-1'
  22. }
  23. }"
  24. ></cl-input>
  25. </view>
  26. <view class="relative flex flex-row items-center mb-5">
  27. <cl-input
  28. v-model="form.smsCode"
  29. :clearable="false"
  30. type="number"
  31. prefix-icon="shield-check-fill"
  32. :placeholder="t('请输入验证码')"
  33. :maxlength="4"
  34. :border="false"
  35. :pt="{
  36. className: parseClass([
  37. '!h-[90rpx] flex-1 !rounded-xl !px-4',
  38. [isDark, '!bg-surface-70', '!bg-white']
  39. ]),
  40. prefixIcon: {
  41. className: 'mr-1'
  42. }
  43. }"
  44. >
  45. </cl-input>
  46. <view class="absolute right-0">
  47. <sms-btn
  48. :ref="refs.set('smsBtn')"
  49. :phone="form.phone"
  50. @success="showCode = true"
  51. ></sms-btn>
  52. </view>
  53. </view>
  54. <cl-button
  55. :pt="{
  56. className: '!h-[90rpx] !rounded-xl'
  57. }"
  58. :loading="loading"
  59. :disabled="disabled"
  60. @tap="toLogin"
  61. >
  62. {{ t("登录") }}
  63. </cl-button>
  64. </view>
  65. </template>
  66. <script setup lang="ts">
  67. import { t } from "@/locale";
  68. import { computed, inject, ref, type PropType } from "vue";
  69. import type { LoginForm } from "../../types";
  70. import SmsBtn from "@/components/sms-btn.uvue";
  71. import { isDark, parseClass, request, useRefs, type Response } from "@/cool";
  72. import { useUi } from "@/uni_modules/cool-ui";
  73. const props = defineProps({
  74. form: {
  75. type: Object as PropType<LoginForm>,
  76. default: () => ({})
  77. }
  78. });
  79. const emit = defineEmits(["success"]);
  80. const ui = useUi();
  81. const refs = useRefs();
  82. // 是否同意
  83. const isAgree = inject("isAgree") as () => boolean;
  84. // 是否显示验证码
  85. const showCode = ref(false);
  86. // 是否加载中
  87. const loading = ref(false);
  88. // 是否禁用
  89. const disabled = computed(() => {
  90. return props.form.phone == "" || props.form.smsCode == "";
  91. });
  92. // 登录
  93. async function toLogin() {
  94. if (!isAgree()) {
  95. return;
  96. }
  97. const { phone, smsCode } = props.form;
  98. loading.value = true;
  99. await request({
  100. url: "/app/user/login/phone",
  101. method: "POST",
  102. data: {
  103. phone,
  104. smsCode
  105. }
  106. })
  107. .then((res) => {
  108. emit("success", res);
  109. })
  110. .catch((err) => {
  111. ui.showToast({
  112. message: (err as Response).message!
  113. });
  114. });
  115. loading.value = false;
  116. }
  117. </script>