Browse Source

new changes

master
Ilya_Chis 2 months ago
parent
commit
04d9162fff
  1. 8
      webApp/__init__.py
  2. 1
      webApp/helper/jinjaHelper.py
  3. 2
      webApp/interfaces/dependencies.py
  4. 20
      webApp/interfaces/pagesController.py
  5. 58
      webApp/templates/2.0/main_page.pug
  6. 75
      webApp/templates/static/css/1_model_app.css
  7. 8
      webApp/templates/static/css/1_model_icons.css
  8. 387
      webApp/templates/static/js/2.0.dashboard.js
  9. 4
      web_run.py

8
webApp/__init__.py

@ -12,15 +12,15 @@ webApp = Flask(__name__, instance_relative_config=True, template_folder=config['
__version__ = '1.0.1.0'
webApp.config['SECRET_KEY'] = '2qwtq2'
webApp.config['INTERNAL_API_KEY'] = 'lGR9g09RW5cE07rKivRNIH9f'
webApp.config['REMOTE_LOGIN_KEY'] = 'oRTiLTHeNTraZEsI'
webApp.config['SECRET_KEY'] = '2qwtsdfsdfsdfsdfq2'
webApp.config['INTERNAL_API_KEY'] = 'lGR9g09RW5cEsdfsfsdfsdf07rKivRNIH9f'
webApp.config['REMOTE_LOGIN_KEY'] = 'sdfsdfsdfsdf'
webApp.config['SESSION_COOKIE_SAMESITE'] = "None"
webApp.config['SESSION_COOKIE_SECURE'] = True
webApp.jinja_env.add_extension('pypugjs.ext.jinja.PyPugJSExtension')
logging.basicConfig(level = logging.INFO)
# logging.basicConfig(level = logging.INFO)
from webApp.helper import jinjaHelper
from webApp.interfaces import *

1
webApp/helper/jinjaHelper.py

@ -14,4 +14,5 @@ def example():
else:
return config.config['WEB_APP']['FRONTEND_VERSION']
return dict(randomString = randomString)

2
webApp/interfaces/dependencies.py

@ -13,4 +13,4 @@ def send_css(path):
def send_js(path):
resp = make_response(send_from_directory(os.path.join(config['WEB_APP']['template_folder'], 'static/js'), path), 200)
resp.headers['Cache-Control'] = 'public, max-age=31536000'
return resp
return resp

20
webApp/interfaces/pagesController.py

@ -18,6 +18,15 @@ def authorize_google():
client = gspread.authorize(creds)
return client
# Функция проверки существования пользователя в таблице
def user_exists(sheet, fio, tel): #, user_id):
records = sheet.get_all_values() # Получаем все данные таблицы без заголовков
for row in records[1:]: # Пропускаем первую строку, если там заголовки, или уберите [1:], если заголовков нет
if len(row) > 1 and row[0] == fio and row[1] == tel:# and row[13] == user_id:
return True # Если ФИО, телефон и user_id совпадают, значит, запись уже существует
return False
# Обработка формы
@webApp.route('/form_submit', methods=['POST'])
@ -25,20 +34,25 @@ def form_submit():
data = json.loads(request.data)
# {'fio': '', 'tel': '', 'email': '', 'passport': '', 'passport_date': '', 'postal_code': '', 'address': '', 'snils': '', 'inn': '', 'dob': ''}
data['current_time'] = datetime.datetime.now().strftime("%d.%m.%Y, %H:%M")
print(data)
# Авторизация и добавление данных в Google Sheets
sheet = authorize_google().open("Информация о сотрудниках").sheet1
# Проверка, существует ли уже пользователь
if user_exists(sheet, data['fio'], data['tel']): #, data['user_id']):
return jsonify({'success': False, 'error': 'Ваши данные уже присутствуют в таблице'}), 400
sheet.append_row([
data['fio'],
data['tel'],
data['email'],
data['passport'][:4],
data['passport'][4:],
data['passport'][:5],
data['passport'][5:],
data['passport_issued_by'],
data['passport_date'],
data['postal_code'],
data['address'],
data['residential_address'],
data['snils'],
data['inn'],
data['dob'],

58
webApp/templates/2.0/main_page.pug

@ -1,8 +1,8 @@
include 2.0/application
link(rel="stylesheet" href="/css/1_model_app.css")
link(rel="stylesheet" href="/css/1_model_icons.css")
link(rel="stylesheet" href="/css/1_model_app.css?q="~randomString())
link(rel="stylesheet" href="/css/1_model_icons.css?q="~randomString())
script(type="text/javascript", src="/js/UFMS.js?q="~randomString())
script(type="text/javascript", src="/js/2.0.dashboard.js?q="~randomString())
@ -13,39 +13,61 @@ script(type="text/javascript", src="/js/2.0.dashboard.js?q="~randomString())
.card-body.px-0.pb-0
h5.mx-4.fw-bold="Заполните форму"
input.tg_input#user_id(hidden, value=user_id)
//--.my-3.mx-4
.alert-placeholder.alert-lg.text-warning(data-content='У данного пользователя отсутсвуют права для направления пациентов')
input.form-control.form-control.custom-input#form_name(type="text")
.my-3.mx-4
label.form-label.m-0(for="fio")='ФИО'
input.form-control.tg_input#fio
.my-3.mx-4
label.form-label.m-0(for="tel")='Телефон'
input.form-control.tg_input#tel
.my-3.mx-4
.my-3.mx-4.success-field
label.form-label.m-0(for="tel")="Телефон"
input.form-control.tg_input#tel(type="text")
small="(Пожалуйста, проверьте формат ввода)"
.my-3.mx-4.success-field
label.form-label.m-0(for="dob")='Дата рождения'
input.form-control.tg_input#dob(type="date")
small="(Пожалуйста, проверьте формат ввода)"
.my-3.mx-4.success-field
label.form-label.m-0(for="email")='Электронная почта'
input.form-control.tg_input#email
.my-3.mx-4
small="(Пожалуйста, проверьте формат ввода)"
.my-3.mx-4.success-field
label.form-label.m-0(for="passport")='Серия и номер паспорта'
input.form-control.tg_input#passport
.my-3.mx-4
small="(Пожалуйста, проверьте формат ввода)"
.my-3.mx-4.success-field
label.form-label.m-0(for="passport_date")='Дата выдачи паспорта'
input.form-control.tg_input#passport_date(type="date")
.my-3.mx-4
label.form-label.m-0(for="postal_code")='Кем выдан'
input.form-control.tg_input#passport_issued_by
.my-3.mx-4
small="(Пожалуйста, проверьте формат ввода)"
.my-3.mx-4.success-field
label.form-label.m-0(for="postal_code")='Код подразделения'
input.form-control.tg_input#postal_code
small="(Пожалуйста, проверьте формат ввода)"
.my-3.mx-4
label.form-label.m-0(for="passport_issued_by")='Кем выдан паспорт'
select.form-select.tg_input#passport_issued_by(style="")
option(disabled, selected)="Кем выдан паспорт"
.my-3.mx-4
label.form-label.m-0(for="address")='Место жительства'
label.form-label.m-0(for="address")='Адрес регистрации'
input.form-control.tg_input#address
.my-3.mx-4
label.form-label.m-0(for="residential_address")='Адрес проживания'
input.form-control.tg_input#residential_address
.my-3.mx-4.success-field
label.form-label.m-0(for="snils")='СНИЛС'
input.form-control.tg_input#snils
.my-3.mx-4
small="(Пожалуйста, проверьте формат ввода)"
.my-3.mx-4.success-field
label.form-label.m-0(for="inn")='ИНН'
input.form-control.tg_input#inn
.my-3.mx-4
label.form-label.m-0(for="dob")='Дата рождения'
input.form-control.tg_input#dob(type="date")
small="(Пожалуйста, проверьте формат ввода)"
.my-3.mx-4
button.btn.btn-success.float-end.mb-3#form_submit
span.spinner-border.spinner-border-sm.me-1.d-none(role="status" aria-hidden="true")

75
webApp/templates/static/css/1_model_app.css

@ -666,4 +666,79 @@ PLUS DROPDOWN
.hotkey-card:focus{
border: 1px solid blue !important;
}
.success-field input{
/*border: 1px solid #000;*/
}
.errors-field input{
border: 1px solid #F00;
}
.success-field small{
display: none;
}
.errors-field small{
color: #F00;
margin-left: 10px;
font-size: 0.7em;
font-style: italic;
display: block;
}
#passport-error {
display: none; /* Скрыть по умолчанию */
color: #F00; /* Красный цвет для ошибки */
}
select {
border: 1px solid #838383;
border-style: outset;
font-weight: bold;
color: #3F3F3F;
max-width: 100% !important;
overflow: hidden;
}
option {
max-width: 120px !important;
overflow: hidden;
}
.alert-placeholder
{
position: relative;
color: attr(data-color) !important;
font-size: 20px;
white-space: nowrap;
}
.alert-lg:before{
top: 4px;
}
.alert-md:before{
top: 4px;
}
.alert-sm:before{
top: 1px;
}
.alert-placeholder:before
{
position: absolute;
right: 15px;
font-family: 'Font Awesome\ 5 Free';
content: "\f071";
font-weight: 900;
pointer-events: none;
opacity: 1;
overflow: hidden;
text-overflow: clip;
}
.alert-popover{
top: 0px !important;
left: calc(50% - 124px) !important;
width: 250px !important;
}

8
webApp/templates/static/css/1_model_icons.css

@ -7,6 +7,14 @@
margin-right: 3px;
}
.warning-icn::before {
font-family: 'Font Awesome\ 5 Free';
content: "\f071";
font-weight: 900;
margin-right: 3px;
color: orange;
}
.m-off::before{
margin: 0px !important;
}

387
webApp/templates/static/js/2.0.dashboard.js

@ -20,10 +20,223 @@ function validate_length(val, dest_len){
}
$(document).ready(function(){
const validateEmail = (email) => {
return email.match(
/^(([^<>()[\]\\.,;:\s@\"]+(\.[^<>()[\]\\.,;:\s@\"]+)*)|(\".+\"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/
);
};
const validate = () => {
const email = $('#email').val();
if(validateEmail(email)){
$('#email').parent().removeClass('errors-field').addClass('success-field');
} else{
$('#email').parent().removeClass('success-field').addClass('errors-field');
}
return false;
}
$('#email').on('input', validate);
$('body').append('<div id="error_alert" class="alert alert-danger" role="alert" style="position: fixed; top: 50px; left: 10%; right: 10%; z-index: 9999; display: none;">Ошибка<br><small id="alert_error_text"></small></div>');
$('body').append('<div id="success_alert" class="alert alert-success" role="alert" style="position: fixed; top: 50px; left: 10%; right: 10%; z-index: 9999; display: none;">Успех<br><small id="alert_success_text"></small></div>');
$('#fio').on("input", function(){
console.log($('#fio').val());
$('#fio').on('input', function() {
let input = $(this).val();
input = input.replace(/[^a-zA-Zа-яА-ЯёЁ ]/g, '');
// Разделение текста по пробелам и преобразование каждого слова
let words = input.split(/\s+/); // Разбиваем по пробелам
// Преобразуем каждое слово
let formattedInput = words.map(word => {
if (word.length > 0) {
return word.charAt(0).toUpperCase() + word.slice(1).toLowerCase();
}
return ''; // Если слово пустое (например, несколько пробелов), не изменяем
}).join(' '); // Объединяем обратно с пробелами
// Обновляем поле ввода с отформатированным текстом
$(this).val(formattedInput);
});
$('#email').on('input', function() {
let input = $(this).val();
// Разрешаем только буквы, цифры, точки, дефисы и подчеркивания
input = input.replace(/[^a-zA-Z0-9._@-]/g, '');
// Обновляем поле ввода
$(this).val(input);
});
$('#tel').on('change', function() {
if($(this).val().length != 16){
$(this).parent().removeClass('success-field').addClass('errors-field');
} else{
$(this).parent().removeClass('errors-field').addClass('success-field');
}
});
// Проверка на дату рождения (не старше 80 лет)
$('#dob').on('change', function() {
const dob = new Date($(this).val());
const currentDate = new Date();
const age = currentDate.getFullYear() - dob.getFullYear();
// Проверка на возраст (не старше 80 лет)
if (age > 80 || (age === 80 && (currentDate.getMonth() < dob.getMonth() || (currentDate.getMonth() === dob.getMonth() && currentDate.getDate() < dob.getDate())))) {
// Если возраст больше 80 лет, подсвечиваем ячейку как ошибку
$(this).parent().removeClass('success-field').addClass('errors-field');
} else {
// Если возраст нормален, подсвечиваем ячейку как успешную
$(this).parent().removeClass('errors-field').addClass('success-field');
}
});
// Проверка на дату выдачи паспорта (выдан после 14, 20 или 45 лет)
$('#passport_date').on('change', function() {
const passportDate = new Date($(this).val());
const dob = new Date($('#dob').val());
// Проверка, что дата рождения введена и корректна
if (!dob || isNaN(dob)) {
// Если дата рождения не введена или неверна, показываем ошибку
$(this).parent().removeClass('success-field').addClass('errors-field');
return;
}
const ageAtPassportIssue = passportDate.getFullYear() - dob.getFullYear();
// Проверка на возраст, в котором может быть выдан паспорт
if (ageAtPassportIssue === 14 || ageAtPassportIssue === 20 || ageAtPassportIssue === 45) {
// Если возраст при выдаче паспорта соответствует требованиям, подсвечиваем ячейку как успешную
$(this).parent().removeClass('errors-field').addClass('success-field');
} else {
// Если возраст не соответствует, показываем ошибку
$(this).parent().removeClass('success-field').addClass('errors-field');
}
});
$("#passport").attr('maxlength','12');
$('#passport').on('input', function() {
let input = $(this).val();
// Удаляем все символы, кроме цифр и пробелов
input = input.replace(/\D/g, '');
// Форматируем ввод в "00 00 000000" с пробелами
if (input.length > 2 && input.length <= 4) {
input = input.replace(/(\d{2})(\d{0,2})/, '$1 $2');
} else if (input.length > 4 && input.length <= 10) {
input = input.replace(/(\d{2})(\d{2})(\d{0,6})/, '$1 $2 $3');
}
// Ограничиваем длину до "00 00 000000"
if (input.length > 12) {
input = input.slice(0, 12);
}
// Обновляем поле ввода
$(this).val(input);
// Проверка на минимальную длину (не менее 11 символов)
if (input.length < 12) {
// Если введено меньше цифр, показываем ошибку
$(this).parent().removeClass('success-field').addClass('errors-field');
} else {
// Если введено достаточно цифр, показываем успех
$(this).parent().removeClass('errors-field').addClass('success-field');
}
});
$('#postal_code').on('input', function() {
let input = $(this).val();
// Удаляем все символы, кроме цифр
input = input.replace(/\D/g, '');
// Форматируем ввод в "000-000" только при наличии 4 и более цифр
if (input.length > 3) {
input = input.replace(/(\d{3})(\d{0,3})/, '$1-$2');
}
// Ограничиваем длину до "000-000"
if (input.length > 7) {
input = input.slice(0, 7);
}
// Обновляем поле ввода
$(this).val(input);
// Проверка на минимальную длину (не менее 11 символов)
if (input.length < 7) {
// Если введено меньше цифр, показываем ошибку
$(this).parent().removeClass('success-field').addClass('errors-field');
} else {
// Если введено достаточно цифр, показываем успех
$(this).parent().removeClass('errors-field').addClass('success-field');
}
});
$('#passport_issued_by').select2({
theme: 'bootstrap-5'
});
$("#postal_code").change(function(){
$('#passport_issued_by').empty();
$('#passport_issued_by').append('<option disabled="" selected="">Кем выдан паспорт</option>')
for(i in UFMS_list[$(this).val()])
{
item = UFMS_list[$(this).val()][i];
$('#passport_issued_by').append('<option>'+item+'</option>');
}
// $('#passport_issued_by').select2("change");
});
$('#snils').on('input', function() {
let input = $(this).val();
// Удаляем все символы, кроме цифр
input = input.replace(/\D/g, '');
// Форматируем ввод в "000-000-000-00" только после 3, 6, 9 цифр
if (input.length > 3 && input.length <= 6) {
input = input.replace(/(\d{3})(\d{0,3})/, '$1-$2');
} else if (input.length > 6 && input.length <= 9) {
input = input.replace(/(\d{3})(\d{3})(\d{0,3})/, '$1-$2-$3');
} else if (input.length > 9) {
input = input.replace(/(\d{3})(\d{3})(\d{3})(\d{0,2})/, '$1-$2-$3-$4');
}
// Ограничиваем длину до "000-000-000-00"
if (input.length > 14) {
input = input.slice(0, 14);
}
// Обновляем поле ввода
$(this).val(input);
if (input.length < 14) {
// Если введено меньше цифр, показываем ошибку
$(this).parent().removeClass('success-field').addClass('errors-field');
} else {
// Если введено достаточно цифр, показываем успех
$(this).parent().removeClass('errors-field').addClass('success-field');
}
});
$("#inn").attr('maxlength','12');
$('#inn').on('input', function() {
let input = $(this).val();
// Убираем все символы, кроме цифр
input = input.replace(/\D/g, '');
// Ограничиваем длину до 12 символов
if (input.length > 12) {
input = input.slice(0, 12);
}
// Обновляем значение в поле ввода
$(this).val(input);
if (input.length < 12) {
// Если введено меньше цифр, показываем ошибку
$(this).parent().removeClass('success-field').addClass('errors-field');
} else {
// Если введено достаточно цифр, показываем успех
$(this).parent().removeClass('errors-field').addClass('success-field');
}
});
$("#form_submit").click(function(){
@ -31,7 +244,6 @@ $(document).ready(function(){
$(this).attr("disabled", true);
message = {}
if(!(validate_length($('#fio').val(), 3)))
{
show_error('Введите ФИО', false);
@ -40,10 +252,96 @@ $(document).ready(function(){
return;
}
if(!(validate_length($('#tel').val(), 16)))
{
show_error('Введите Телефон', false);
$(this).children(".spinner-border").addClass('d-none');
$(this).removeAttr("disabled");
return;
}
if ($('#dob').val().length !== 10 || new Date().getFullYear() - new Date($('#dob').val()).getFullYear() > 80) {
show_error('Дата рождения должна быть корректной и возраст не более 80 лет', false);
$(this).children(".spinner-border").addClass('d-none');
$(this).removeAttr("disabled");
return;
}
if(!(validateEmail($('#email').val()))){
show_error('Введите корректный Email', false);
$(this).children(".spinner-border").addClass('d-none');
$(this).removeAttr("disabled");
return;
}
if(!(validate_length($('#passport').val(), 12)))
{
show_error('Введите серию и номер паспорта', false);
$(this).children(".spinner-border").addClass('d-none');
$(this).removeAttr("disabled");
return;
}
if ($('#passport_date').val().length !== 10 || ![14, 20, 45].includes(new Date($('#passport_date').val()).getFullYear() - new Date($('#dob').val()).getFullYear())) {
show_error('Дата выдачи паспорта должна быть в 14, 20 или 45 лет', false);
$(this).children(".spinner-border").addClass('d-none');
$(this).removeAttr("disabled");
return;
}
if(!(validate_length($('#postal_code').val(), 7)))
{
show_error('Введите код подразделения', false);
$(this).children(".spinner-border").addClass('d-none');
$(this).removeAttr("disabled");
return;
}
if($('#passport_issued_by').val() == null){
show_error("Выберите кем выдан паспорт");
$(this).children(".spinner-border").addClass('d-none');
$(this).removeAttr("disabled");
return;
}
if(!(validate_length($('#address').val(), 3)))
{
show_error('Введите адрес регистрации', false);
$(this).children(".spinner-border").addClass('d-none');
$(this).removeAttr("disabled");
return;
}
if(!(validate_length($('#residential_address').val(), 3)))
{
show_error('Введите адрес проживания', false);
$(this).children(".spinner-border").addClass('d-none');
$(this).removeAttr("disabled");
return;
}
if(!(validate_length($('#snils').val(), 14)))
{
show_error('Введите СНИЛС', false);
$(this).children(".spinner-border").addClass('d-none');
$(this).removeAttr("disabled");
return;
}
if(!(validate_length($('#inn').val(), 12)))
{
show_error('Введите ИНН', false);
$(this).children(".spinner-border").addClass('d-none');
$(this).removeAttr("disabled");
return;
}
$.each($('.tg_input'), function(e) {
message[$(this).prop("id")] = $(this).val();
});
console.log(message);
$.ajax({
type: "post",
url: "/form_submit",
@ -64,4 +362,83 @@ $(document).ready(function(){
}
});
});
});
// $('.alert-placeholder').mouseenter(function(){
// var popOverSettings = {
// placement: 'bottom',
// content: $(this).data('content'),
// trigger: 'hover',
// container: this,
// offset: '0'
// }
// $(this).popover(popOverSettings);
// $(this).popover('show');
// $('.popover').addClass('alert-popover');
// });
// $('.alert-placeholder').mouseleave(function(){
// $('.alert-popover').remove()
// });
let phoneStr = '';
let formattedStr = '';
let deleteMode = false;
const phoneInput = document.querySelector('#tel');
const defaultFormat = '+7({0}{1}{2}){3}{4}{5}-{6}{7}-{8}{9}';
phoneInput.value = formatPhoneString();
phoneInput.addEventListener('keydown', (e) => {
if (e.key === 'Backspace')
deleteMode = true;
else
deleteMode = false;
});
7
phoneInput.addEventListener('input', (e) => {
if (deleteMode) {
phoneInput.value = phoneInput.value;
phoneStr = parsePhoneString(phoneInput.value.replace("+7", "").replace("-", ""));
} else {
if (e.inputType == 'insertText' && !isNaN(parseInt(e.data))) {
if (phoneStr.length <= 9)
phoneStr += e.data;
}
phoneInput.value = formatPhoneString();
}
});
function formatPhoneString() {
let strArr = phoneStr.split('');
formattedStr = defaultFormat;
for (let i = 0; i < strArr.length; i++) {
formattedStr = formattedStr.replace(`{${i}}`, strArr[i]);
}
if (formattedStr.indexOf('{') === -1)
{
return formattedStr;
}
else
{
return formattedStr.substring(0, formattedStr.indexOf('{'));
}
}
function parsePhoneString(str) {
return str.replace(' ', '').replace('(', '').replace(')', '').replace('-', '');
}
});

4
web_run.py

@ -4,5 +4,5 @@ from waitress import serve
from config import config
if __name__ == '__main__':
# webApp.run(debug=True, port=config['WEB_APP']['PORT'])
serve(webApp, host='0.0.0.0', port=config['WEB_APP']['PORT'])
webApp.run(debug=True, port=config['WEB_APP']['PORT'])
#serve(webApp, host='0.0.0.0', port=config['WEB_APP']['PORT'])
Loading…
Cancel
Save