phone-international-input.vue 3.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131
  1. <!-- 国际手机输入组件 -->
  2. <template>
  3. <picker mode="selector" :range="country.map(item => item.chinese_name +' +'+ item.phone_code)" :value="selectedIndex"
  4. @change="pickChange" style="float: left;height: 100%;width: 110rpx;display: flex;align-items: center;">
  5. <view>+{{selectedCode}}
  6. <image src="@/static/icon/select-icon.png" style="width: 20rpx;height: 20rpx;" />
  7. </view>
  8. </picker>
  9. <uni-easyinput placeholder="请输入手机号" v-model="state.model.mobile" @input="verifyMobile" :inputBorder="false" type="number" style="float: left;width: calc(100% - 110rpx);">
  10. <template v-slot:right>
  11. <button class="ss-reset-button code-btn code-btn-start" :disabled="!verifyUsername || selectedCode != 86"
  12. :class="{ 'disabled': !verifyUsername || selectedCode != 86}" @tap="getSmsCode('smsLogin', state.model.mobile)">
  13. {{ getSmsTimer('smsLogin') }}
  14. </button>
  15. </template>
  16. </uni-easyinput>
  17. </template>
  18. <script setup>
  19. import {
  20. ref,
  21. reactive,
  22. unref,
  23. computed
  24. } from 'vue';
  25. import sheep from '@/sheep';
  26. import {
  27. getSmsCode,
  28. getSmsTimer
  29. } from '@/sheep/hooks/useModal';
  30. import {
  31. onLoad
  32. } from '@dcloudio/uni-app';
  33. import countryData from '@/sheep/libs/country.json';
  34. import {parsePhoneNumberFromString,AsYouType } from 'libphonenumber-js';
  35. import parseMobile from 'libphonenumber-js/mobile'
  36. const country = ref(countryData);
  37. const selectedCode = ref('');
  38. const selectedCountryCode = ref('');
  39. const selectedIndex = ref(0);
  40. // 查找中国在 country 数组中的索引
  41. const findIndexByCode = (code) => {
  42. return country.value.findIndex(item => item.phone_code == code);
  43. };
  44. // 更新选中的国家代码和索引
  45. const pickChange = (e) => {
  46. selectedIndex.value = e.detail.value;
  47. selectedCode.value = country.value[selectedIndex.value].phone_code;
  48. selectedCountryCode.value = country.value[selectedIndex.value].country_code;
  49. };
  50. // 设置默认选中中国
  51. onLoad(() => {
  52. const chinaIndex = findIndexByCode('86');
  53. if (chinaIndex !== -1) {
  54. selectedIndex.value = chinaIndex;
  55. selectedCode.value = country.value[chinaIndex].phone_code;
  56. selectedCountryCode.value = country.value[chinaIndex].country_code;
  57. }
  58. });
  59. const props = defineProps({
  60. verifyUsername: {
  61. type: Boolean
  62. }
  63. });
  64. const emits = defineEmits(['input']);
  65. const verifyMobile = (e) => {
  66. // console.log(e.detail.value)
  67. const phone = e;
  68. if(phone == ''){
  69. emits('input',phone,'请输入手机号')
  70. } else {
  71. try{
  72. const phoneParseMobile = parseMobile(phone, selectedCountryCode.value);
  73. if(phoneParseMobile.isValid()){
  74. emits('input',phone,'')
  75. }else{
  76. emits('input',phone,'手机号码格式不正确')
  77. }
  78. }catch(e){
  79. // console.log(e)
  80. }
  81. }
  82. }
  83. // 账号注册数据
  84. const state = reactive({
  85. codeText: '获取验证码',
  86. model: {
  87. mobile: '', // 手机号
  88. }
  89. });
  90. </script>
  91. <style lang="scss" scoped>
  92. @import '../index.scss';
  93. .code-btn-start {
  94. color: var(--ui-BG-Main);
  95. border: 1px solid var(--ui-BG-Main);
  96. }
  97. .disabled {
  98. border: 1px solid #f7f7f7;
  99. }
  100. .loginUniForm {
  101. border: 1rpx solid #d6d6d6;
  102. padding: 10rpx 15rpx;
  103. border-radius: 10rpx;
  104. }
  105. .loginUniFormItem {
  106. border-bottom: 1rpx solid #d6d6d6;
  107. padding-bottom: 10rpx;
  108. }
  109. .loginUniFormItem:last-child {
  110. border-bottom: none;
  111. padding-top: 10rpx;
  112. }
  113. ::v-deep .loginUniFormItem .uni-forms-item__inner {
  114. padding-bottom: 0;
  115. }
  116. ::v-deep .loginUniFormItem .uni-error-message {
  117. bottom: -20rpx;
  118. }
  119. </style>