perf: 增加国际电话区号选择

pull/12645/head
wangruidong 2024-02-02 16:52:57 +08:00 committed by Bryan
parent 973df0360c
commit f606dd8920
5 changed files with 72 additions and 10 deletions

View File

@ -19,3 +19,17 @@ class Status(models.TextChoices):
failed = 'failed', _("Failed") failed = 'failed', _("Failed")
error = 'error', _("Error") error = 'error', _("Error")
canceled = 'canceled', _("Canceled") canceled = 'canceled', _("Canceled")
COUNTRY_CALLING_CODES = [
{'name': 'China(中国)', 'value': '+86'},
{'name': 'HongKong(中国香港)', 'value': '+852'},
{'name': 'Macao(中国澳门)', 'value': '+853'},
{'name': 'Taiwan(中国台湾)', 'value': '+886'},
{'name': 'America(America)', 'value': '+1'}, {'name': 'Russia(Россия)', 'value': '+7'},
{'name': 'France(français)', 'value': '+33'},
{'name': 'Britain(Britain)', 'value': '+44'},
{'name': 'Germany(Deutschland)', 'value': '+49'},
{'name': 'Japan(日本)', 'value': '+81'}, {'name': 'Korea(한국)', 'value': '+82'},
{'name': 'India(भारत)', 'value': '+91'}
]

View File

@ -3,6 +3,7 @@ from rest_framework import generics
from rest_framework.permissions import AllowAny from rest_framework.permissions import AllowAny
from authentication.permissions import IsValidUserOrConnectionToken from authentication.permissions import IsValidUserOrConnectionToken
from common.const.choices import COUNTRY_CALLING_CODES
from common.utils import get_logger, lazyproperty from common.utils import get_logger, lazyproperty
from common.utils.timezone import local_now from common.utils.timezone import local_now
from .. import serializers from .. import serializers
@ -24,7 +25,8 @@ class OpenPublicSettingApi(generics.RetrieveAPIView):
def get_object(self): def get_object(self):
return { return {
"XPACK_ENABLED": settings.XPACK_ENABLED, "XPACK_ENABLED": settings.XPACK_ENABLED,
"INTERFACE": self.interface_setting "INTERFACE": self.interface_setting,
"COUNTRY_CALLING_CODES": COUNTRY_CALLING_CODES
} }

View File

@ -11,6 +11,7 @@ __all__ = [
class PublicSettingSerializer(serializers.Serializer): class PublicSettingSerializer(serializers.Serializer):
XPACK_ENABLED = serializers.BooleanField() XPACK_ENABLED = serializers.BooleanField()
INTERFACE = serializers.DictField() INTERFACE = serializers.DictField()
COUNTRY_CALLING_CODES = serializers.ListField()
class PrivateSettingSerializer(PublicSettingSerializer): class PrivateSettingSerializer(PublicSettingSerializer):

View File

@ -7,6 +7,7 @@
.margin-bottom { .margin-bottom {
margin-bottom: 15px; margin-bottom: 15px;
} }
.input-style { .input-style {
width: 100%; width: 100%;
display: inline-block; display: inline-block;
@ -22,6 +23,19 @@
height: 100%; height: 100%;
vertical-align: top; vertical-align: top;
} }
.scrollable-menu {
height: auto;
max-height: 18rem;
overflow-x: hidden;
}
.input-group {
.input-group-btn .btn-secondary {
color: #464a4c;
background-color: #eceeef;
}
}
</style> </style>
{% endblock %} {% endblock %}
{% block html_title %}{% trans 'Forgot password' %}{% endblock %} {% block html_title %}{% trans 'Forgot password' %}{% endblock %}
@ -57,9 +71,26 @@
placeholder="{% trans 'Email account' %}" value="{{ email }}"> placeholder="{% trans 'Email account' %}" value="{{ email }}">
</div> </div>
<div id="validate-sms" class="validate-field margin-bottom"> <div id="validate-sms" class="validate-field margin-bottom">
<input type="tel" id="sms" name="sms" class="form-control input-style" <div class="input-group">
placeholder="{% trans 'Mobile number' %}" value="{{ sms }}"> <div class="input-group-btn">
<small style="color: #999; margin-left: 5px">{{ form.sms.help_text }}</small> <button type="button" class="btn btn-secondary dropdown-toggle" data-toggle="dropdown"
aria-haspopup="true" aria-expanded="false">
<span class="country-code-value">+86</span>
</button>
<ul class="dropdown-menu scrollable-menu">
{% for country in countries %}
<li>
<a href="#" class="dropdown-item d-flex justify-content-between">
<span class="country-name text-left">{{ country.name }}</span>
<span class="country-code">{{ country.value }}</span>
</a>
</li>
{% endfor %}
</ul>
</div>
<input type="tel" id="sms" name="sms" class="form-control input-style"
placeholder="{% trans 'Mobile number' %}" value="{{ sms }}">
</div>
</div> </div>
<div class="margin-bottom challenge-required"> <div class="margin-bottom challenge-required">
<input type="text" id="code" name="code" class="form-control input-style" <input type="text" id="code" name="code" class="form-control input-style"
@ -76,7 +107,7 @@
</div> </div>
</div> </div>
<script> <script>
$(function (){ $(function () {
const validateSelectRef = $('#validate-backend-select') const validateSelectRef = $('#validate-backend-select')
const formType = $('input[name="form_type"]').val() const formType = $('input[name="form_type"]').val()
validateSelectRef.val(formType) validateSelectRef.val(formType)
@ -84,19 +115,31 @@
selectChange(formType); selectChange(formType);
} }
}) })
$(".dropdown-menu li a").click(function (evt) {
const inputGroup = $('.input-group');
const inputGroupAddon = inputGroup.find('.country-code-value');
const selectedCountry = $(evt.target).closest('li');
const selectedCountryCode = selectedCountry.find('.country-code').html();
inputGroupAddon.html(selectedCountryCode)
});
function getQueryString(name) { function getQueryString(name) {
const reg = new RegExp("(^|&)"+ name +"=([^&]*)(&|$)"); const reg = new RegExp("(^|&)" + name + "=([^&]*)(&|$)");
const r = window.location.search.substr(1).match(reg); const r = window.location.search.substr(1).match(reg);
if(r !== null) if (r !== null)
return unescape(r[2]) return unescape(r[2])
return null return null
} }
function selectChange(name) { function selectChange(name) {
$('.validate-field').hide() $('.validate-field').hide()
$('#validate-' + name).show() $('#validate-' + name).show()
$('#validate-' + name + '-tip').show() $('#validate-' + name + '-tip').show()
$('input[name="form_type"]').attr('value', name) $('input[name="form_type"]').attr('value', name)
} }
function sendChallengeCode(currentBtn) { function sendChallengeCode(currentBtn) {
let time = 60; let time = 60;
const token = getQueryString('token') const token = getQueryString('token')
@ -104,7 +147,7 @@
const formType = $('input[name="form_type"]').val() const formType = $('input[name="form_type"]').val()
const email = $('#email').val() const email = $('#email').val()
const sms = $('#sms').val() let sms = $('#sms').val();
const errMsg = "{% trans 'The {} cannot be empty' %}" const errMsg = "{% trans 'The {} cannot be empty' %}"
if (formType === 'sms') { if (formType === 'sms') {
@ -118,10 +161,11 @@
return return
} }
} }
sms = $(".input-group .country-code-value").html() + sms
const data = { const data = {
form_type: formType, email: email, sms: sms, form_type: formType, email: email, sms: sms,
} }
function onSuccess() { function onSuccess() {
const originBtnText = currentBtn.innerHTML; const originBtnText = currentBtn.innerHTML;
currentBtn.disabled = true currentBtn.disabled = true

View File

@ -13,6 +13,7 @@ from django.views.generic import FormView, RedirectView
from authentication.errors import IntervalTooShort from authentication.errors import IntervalTooShort
from authentication.utils import check_user_property_is_correct from authentication.utils import check_user_property_is_correct
from common.const.choices import COUNTRY_CALLING_CODES
from common.utils import FlashMessageUtil, get_object_or_none, random_string from common.utils import FlashMessageUtil, get_object_or_none, random_string
from common.utils.verify_code import SendAndVerifyCodeUtil from common.utils.verify_code import SendAndVerifyCodeUtil
from users.notifications import ResetPasswordSuccessMsg from users.notifications import ResetPasswordSuccessMsg
@ -108,7 +109,7 @@ class UserForgotPasswordView(FormView):
for k, v in cleaned_data.items(): for k, v in cleaned_data.items():
if v: if v:
context[k] = v context[k] = v
context['countries'] = COUNTRY_CALLING_CODES
context['form_type'] = 'email' context['form_type'] = 'email'
context['XPACK_ENABLED'] = settings.XPACK_ENABLED context['XPACK_ENABLED'] = settings.XPACK_ENABLED
validate_backends = self.get_validate_backends_context(has_phone) validate_backends = self.get_validate_backends_context(has_phone)