Каталог

Ручные насосы для шаров

По вашему запросу ничего не найдено

Ручные насосы для шаров: идеальное решение для вашего праздника

При подготовке к празднику многие из нас сталкиваются с необходимостью надувания воздушных шаров. Это могут быть дни рождения, свадьбы, детские праздники и другие мероприятия, где использование шариков создает атмосферу радости и веселья. Ручные насосы для шаров — это незаменимый инструмент, который позволит вам легко и быстро накачать шары для любого события.

Почему стоит выбрать ручные насосы?

Ручные насосы для шаров отличаются своей простотой в использовании и доступны по цене. Они идеально подходят для накачки как обычных, так и гелиевых шаров, что делает их универсальным инструментом для любого праздника. В отличие от электрических насосов, ручные насосы не требуют подключения к сети и могут использоваться в любой удобной обстановке, что особенно важно, если вы планируете мероприятие на улице или в месте, где нет доступа к электроэнергии.

На нашем сайте вы можете купить ручные насосы для шаров оптом или в розницу. Мы предлагаем низкую цену на продукцию, а также возможность заказать насосы с доставкой по всей России, включая Москва. Вы можете легко закупить продукцию на нашем оптовом складе, что будет удобно для организаторов мероприятий и владельцев бизнесов, занимающихся оформлением праздников.

Особенности ручных насосов

Ручные насосы, которые мы предлагаем, подходят не только для обычных воздушных шаров, но и для шаров ШДМ и гелиевых шаров. Это делает их универсальными в использовании. Они обеспечивают быстрое и качественное надувание, что особенно важно при подготовке к мероприятиям, когда время – это ключевой фактор. С их помощью вы сможете быстро и эффективно подготовить декор для любого праздника.

Подходит для различных праздников

Ручные насосы для шаров идеально подойдут для оформления различных праздников, таких как:

  • День рождения – когда каждый элемент декора важен для создания веселой атмосферы.
  • Свадьба – для создания романтической и праздничной обстановки.
  • Детский праздник – чтобы удивить маленьких гостей яркими и красочными шарами.

Атмосфера, созданная с помощью воздушных шаров, всегда впечатляет и радует, а ручные насосы помогут вам в этом.

Сопутствующие товары

Кроме ручных насосов, на нашем сайте вы также найдете электрические насосы, которые могут быть полезны для более крупных мероприятий. Они обеспечивают быстрое надувание большого количества шаров и идеально подходят для профессиональных организаторов праздников. Если вы планируете массовые мероприятия или просто хотите упростить процесс, электрические насосы станут отличным дополнением к вашему арсеналу праздничных принадлежностей.

Как заказать?

Чтобы заказать ручные насосы для шаров, просто выберите нужную модель на нашем сайте. Мы предлагаем удобный интерфейс для быстрого оформления заказа. Вы можете выбрать количество насосов, которое вам нужно, а также оформить доставку на удобное для вас время. Мы гарантируем доставку в любую точку России, а также возможность получения товаров со склада в Москве. Наша компания предоставляет высококачественный сервис и поддержку на всех этапах покупки.

Ручные насосы для шаров – это надежное и недорогое решение для накачки шаров для любого праздника. Мы предлагаем продукцию по доступной цене и с возможностью доставки по всей России. Не упустите шанс создать незабываемую атмосферу на вашем мероприятии! Заказывайте ручные насосы для шаров уже сегодня и наслаждайтесь праздником без лишних хлопот!

Обратный звонок
Запрос успешно отправлен!
Имя *
Телефон *
Предзаказ
Предзаказ успешно отправлен!
Имя *
Телефон *
Добавить в корзину
Название товара
100 ₽
1 шт.
Перейти в корзину
Заявка

Я ознакомлен и согласен с условиями оферты и политики конфиденциальности.

Заявка

Я ознакомлен и согласен с условиями оферты и политики конфиденциальности.

`; } /** * Показ модального окна ошибки оформления заказа */ showOrderErrorModal(result) { // Скрываем успешное окно и показываем ошибку $('.order-success-content').hide(); $('.order-error-content').show(); // Заполняем сообщение об ошибке $('#error-message').text(result.details || result.error || 'Произошла ошибка при оформлении заказа'); this.showModal('Ошибка оформления заказа', '', 'error'); } /** * Создание содержимого модального окна успеха */ createSuccessModalContent(result) { const { orderNumber, paymentMethod, clientType, paymentButton } = result; // Получаем HTML ответ для поиска ключа заказа const $html = $(result.htmlResponse || ''); // Извлекаем информацию о заказе из HTML const orderInfo = this.extractOrderInfo($html); const orderItems = this.extractOrderItems($html); let content = `

Заказ №${orderNumber}

Товары в заказе
${this.createOrderItemsHTML(orderItems)}
${this.createOrderTotalHTML(orderItems)}
Информация о заказе
${this.createOrderInfoHTML(orderInfo, paymentMethod, clientType)} ${paymentMethod === 'Юкасса' && paymentButton ? this.createPaymentSectionHTML(paymentButton, $html) : ''}
`; return content; } /** * Извлечение информации о заказе из HTML */ extractOrderInfo($html) { const info = { orderDate: new Date().toLocaleDateString('ru-RU'), deliveryMethod: 'Доставка курьером', deliveryAddress: '', recipient: '', phone: '', email: '' }; // Извлекаем адрес доставки const addressSelectors = [ '.delivery-address', '.shipping-address', '[class*="address"]' ]; for (const selector of addressSelectors) { const $address = $html.find(selector); if ($address.length > 0) { info.deliveryAddress = $address.text().trim(); break; } } // Извлекаем получателя const recipientSelectors = [ '.recipient-name', '.client-name', '[class*="recipient"]' ]; for (const selector of recipientSelectors) { const $recipient = $html.find(selector); if ($recipient.length > 0) { info.recipient = $recipient.text().trim(); break; } } // Извлекаем телефон и email из формы info.phone = $('#phone').val() || ''; info.email = $('#email').val() || ''; // Если не нашли получателя, используем данные из формы if (!info.recipient) { const firstName = $('#contact_name').val() || ''; const lastName = $('#surname').val() || ''; const middleName = $('#middlename').val() || ''; info.recipient = `${lastName} ${firstName} ${middleName}`.trim(); } // Если не нашли адрес, используем данные из формы if (!info.deliveryAddress) { const city = $('#shipping_address_full_locality_name').val() || ''; const street = $('#shipping_address_street').val() || ''; const house = $('#shipping_address_house').val() || ''; const flat = $('#shipping_address_flat').val() || ''; info.deliveryAddress = `${city}, ${street}, д.${house}${flat ? ', кв.' + flat : ''}`.trim(); } return info; } /** * Извлечение товаров заказа из HTML */ extractOrderItems($html) { const items = []; // Сначала пытаемся получить товары из текущей корзины const $cartItems = $('.cart-item'); const self = this; // Сохраняем контекст if ($cartItems.length > 0) { $cartItems.each(function() { const $item = $(this); const imageSrc = $item.find('img').attr('src') || ''; const item = { name: $item.find('.item-title').text().trim() || 'Товар', sku: $item.find('.item-sku').text().trim() || '', quantity: $item.find('input[name*="quantity"]').val() || '1', price: $item.find('.item-total').text().trim() || '0 ₽', image: self.isValidImageUrl(imageSrc) ? imageSrc : '' }; if (item.name && item.name !== 'Товар') { items.push(item); } }); } // Если не нашли в корзине, ищем в HTML ответе if (items.length === 0) { const itemSelectors = [ '.order-item', '.cart-item', '.product-item', '[class*="item"]' ]; for (const selector of itemSelectors) { const $items = $html.find(selector); if ($items.length > 0) { $items.each(function() { const $item = $(this); const imageSrc = $item.find('img').attr('src') || ''; const item = { name: $item.find('.item-name, .product-name, [class*="name"]').text().trim() || 'Товар', sku: $item.find('.item-sku, .product-sku, [class*="sku"]').text().trim() || '', quantity: $item.find('.item-quantity, .product-quantity, [class*="quantity"]').text().trim() || '1', price: $item.find('.item-price, .product-price, [class*="price"]').text().trim() || '0 ₽', image: self.isValidImageUrl(imageSrc) ? imageSrc : '' }; if (item.name && item.name !== 'Товар') { items.push(item); } }); break; } } } // Если все еще не нашли товары, создаем заглушку if (items.length === 0) { items.push({ name: 'Товары в заказе', sku: '', quantity: '1', price: '0 ₽', image: '' }); } return items; } /** * Создание HTML для товаров заказа */ createOrderItemsHTML(items) { return items.map(item => { const imageHTML = (item.image && this.isValidImageUrl(item.image)) ? `
${item.name || ''}
` : ''; return `
${imageHTML}
${item.name || ''}
${item.sku ? `
Артикул: ${item.sku}
` : ''}
Количество: ${item.quantity || 1}
${item.price || 0}
`; }).join(''); } /** * Создание HTML для итоговой суммы */ createOrderTotalHTML(items) { // Получаем данные из корзины const $cartTotal = $('[data-cart-total-price]'); const $cartDiscount = $('.discount .insales-ui-discounts-errors'); let totalPrice = '0 ₽'; let discountPrice = '0 ₽'; if ($cartTotal.length > 0) { totalPrice = $cartTotal.text().trim() || '0 ₽'; } if ($cartDiscount.length > 0) { const discountText = $cartDiscount.text().trim(); const discountMatch = discountText.match(/(\d+[\s,]*\d*)\s*₽/); if (discountMatch) { discountPrice = discountMatch[0]; } } return `
Скидка: ${discountPrice}
Итого: ${totalPrice}
`; } /** * Создание HTML для информации о заказе */ createOrderInfoHTML(orderInfo, paymentMethod, clientType) { return `
Дата оформления:
${orderInfo.orderDate}
Способ оплаты:
${paymentMethod}
Способ доставки:
${orderInfo.deliveryMethod}
Адрес доставки:
${orderInfo.deliveryAddress || 'Не указан'}
Получатель:
${orderInfo.recipient || 'Не указан'}
Телефон:
${orderInfo.phone || 'Не указан'}
Email:
${orderInfo.email || 'Не указан'}
`; } /** * Создание HTML для секции оплаты */ createPaymentSectionHTML(paymentButton, $html) { // Проверяем, что ссылка корректная let paymentUrl = paymentButton.href; if (!paymentUrl || paymentUrl === 'https://канцопт24.рф/page/payment') { // Если ссылка неправильная, создаем правильную const orderKey = this.extractOrderKey($html); if (orderKey) { paymentUrl = `/payments/external/6146185/create?key=${orderKey}`; } } return `

Для завершения заказа необходимо произвести оплату:

${paymentButton.text || 'Перейти к оплате'}
`; } /** * Создание содержимого модального окна ошибки */ createErrorModalContent(result) { const { error, details } = result; return `

${error}

${details ? `

${details}

` : ''}
`; } /** * Показ модального окна */ showModal(title, content, type = 'info') { const $modal = $('#order-result-modal'); if ($modal.length === 0) { return; } const $modalTitle = $modal.find('.modal-title'); // Устанавливаем заголовок $modalTitle.text(title); // Показываем нужный контент в зависимости от типа if (type === 'success') { $('.order-success-content').show(); $('.order-error-content').hide(); } else if (type === 'error') { $('.order-success-content').hide(); $('.order-error-content').show(); } // Блокируем прокрутку фона (как в CU0.14) const scrollY = window.scrollY; $('body').addClass('modal-open').css({ 'position': 'fixed', 'top': `-${scrollY}px`, 'width': '100%', 'overflow': 'hidden' }); // Принудительно показываем модальное окно $modal.attr('style', ` position: fixed !important; top: 0 !important; left: 0 !important; width: 100% !important; height: 100% !important; background: rgba(0, 0, 0, 0.6) !important; backdrop-filter: blur(4px) !important; z-index: 10000 !important; display: flex !important; align-items: center !important; justify-content: center !important; opacity: 1 !important; pointer-events: auto !important; overflow-y: auto !important; padding: 20px !important; `); // Обработчик закрытия по клику на overlay const self = this; $modal.off('click.modal').on('click.modal', function(e) { // Проверяем, что клик был именно по overlay (не по содержимому) if (e.target === this || $(e.target).hasClass('modal-overlay')) { self.closeModal(); } }); // Обработчик закрытия по клавише Escape $(document).off('keydown.modal').on('keydown.modal', function(e) { if (e.key === 'Escape' || e.keyCode === 27) { self.closeModal(); } }); } /** * Закрытие модального окна */ closeModal() { const $modal = $('#order-result-modal'); if ($modal.length) { // Скрываем модальное окно и отключаем pointer-events $modal.attr('style', 'display: none !important; pointer-events: none !important;'); } // Очищаем обработчики событий $modal.off('click.modal'); $(document).off('keydown.modal'); // Разблокируем прокрутку фона $('body').removeClass('modal-open'); $('body').removeAttr('style'); $('html').removeAttr('style'); // Принудительная перезагрузка с обходом кеша // Используем несколько методов для максимальной надежности на мобильных const currentUrl = window.location.href.split('?')[0].split('#')[0]; const timestamp = new Date().getTime(); const newUrl = currentUrl + '?nocache=' + timestamp; // Используем replace вместо reload для более агрессивной очистки window.location.replace(newUrl); } /** * Сброс виджета */ resetWidget() { // Проверяем, нужно ли сбрасывать состояние // Сбрасываем только для авторизованных + незарегистрированных // Для авторизованных + зарегистрированных НЕ сбрасываем if (this.clientState.isAuthorized && this.clientState.isRegistered) { // Не сбрасываем состояние для авторизованных и зарегистрированных return; } this.clientState = { isAuthorized: false, isRegistered: false, email: null, clientType: 'individual', clientData: null, authCodeSent: false, codeTimer: null }; localStorage.removeItem('client_auth'); $('#order-form')[0].reset(); $('#auth-email-form')[0].reset(); $('#auth-code-form')[0].reset(); $('#order-success-step').removeClass('active'); $('#order-form-step').removeClass('active'); $('#auth-code-step').removeClass('active'); $('#auth-email-step').addClass('active'); this.updateUI(); } /** * Обновление UI */ updateUI() { if (this.clientState.isAuthorized) { this.showAuthSuccess(this.clientState.email); // Скрываем заголовок авторизации для авторизованного клиента $('.auth-header').hide(); // Заполняем email для авторизованного клиента if (this.clientState.email) { $('#email').val(this.clientState.email); $('#email').prop('disabled', true); $('#email').addClass('disabled-field'); } // Проверяем наличие данных клиента (id ИЛИ email + name) const hasValidClientData = this.clientState.clientData && (this.clientState.clientData.id || (this.clientState.clientData.email && this.clientState.clientData.name)); if (this.clientState.isRegistered && hasValidClientData) { this.fillFormWithClientData(); this.showClientStatus(); // Сворачиваем блок организации для авторизованных юр.лиц if (this.clientState.clientType === 'juridical') { this.collapseOrgSectionForAuthUser(); } } } else { // Показываем заголовок авторизации для неавторизованного клиента $('.auth-header').show(); // Разблокируем поле email для неавторизованного клиента $('#email').prop('disabled', false); $('#email').removeClass('disabled-field'); $('#email').val(''); // Очищаем поле // Очищаем статус организации this.setStatusOrgName(null); // Показываем селектор типа клиента this.showClientTypeSelector(); $('#auth-email-step').addClass('active'); $('#auth-code-step').removeClass('active'); $('#auth-success-step').removeClass('active'); } } /** * Таймер для повторной отправки кода */ startCodeTimer() { // Сначала останавливаем предыдущий таймер, если он был запущен this.stopCodeTimer(); // Блокируем кнопку и показываем таймер $('#resend-code-btn').prop('disabled', true).text('Отправить повторно'); $('.code-timer').show(); this.timerSeconds = 60; this.updateTimerDisplay(); // Показываем начальное значение this.codeTimer = setInterval(() => { this.timerSeconds--; if (this.timerSeconds <= 0) { // Разблокируем кнопку повторной отправки и скрываем таймер $('#resend-code-btn').prop('disabled', false).text('Отправить повторно'); $('.code-timer').hide(); this.stopCodeTimer(); } else { this.updateTimerDisplay(); } }, 1000); } /** * Остановка таймера кода */ stopCodeTimer() { if (this.codeTimer) { clearInterval(this.codeTimer); this.codeTimer = null; } } /** * Обновление отображения таймера */ updateTimerDisplay() { const minutes = Math.floor(this.timerSeconds / 60); const seconds = this.timerSeconds % 60; $('#code-timer-text').html(`Повторная отправка через: ${minutes}:${seconds.toString().padStart(2, '0')} сек`); } /** * Показ поля ввода email */ showEmailInput() { $('#auth-code-step').removeClass('active'); $('#auth-email-step').addClass('active'); this.clientState.authCodeSent = false; } /** * Обработка повторной отправки кода */ async handleResendCode() { const email = $('#auth-email').val().trim(); if (!email) { this.showNotification('Нет сохраненного email для повторной отправки', 'error'); return; } // Блокируем кнопку (текст остаётся "Отправить повторно") $('#resend-code-btn').prop('disabled', true); try { const result = await this.sendAuthCode(email); if (result.success) { this.showNotification('Код отправлен повторно', 'success'); // Запускаем таймер (он сам покажет таймер и заблокирует кнопку) this.startCodeTimer(); } else { this.showNotification(result.errors || result.error, 'error'); // При ошибке разблокируем кнопку $('#resend-code-btn').prop('disabled', false); } } catch (error) { this.showNotification('Ошибка повторной отправки кода', 'error'); // При ошибке разблокируем кнопку $('#resend-code-btn').prop('disabled', false); } } /** * Обработка смены email */ handleChangeEmail() { // Останавливаем таймер this.stopCodeTimer(); // Очищаем поля $('#auth-email').val(''); $('#auth-code').val(''); // Возвращаемся к форме ввода email this.showEmailInput(); // Фокусируемся на поле email setTimeout(() => { $('#auth-email').focus(); }, 100); } /** * Показ состояния загрузки */ showLoading(selector) { $(selector).addClass('loading'); } /** * Скрытие состояния загрузки */ hideLoading(selector) { $(selector).removeClass('loading'); } /** * Показ ошибки */ showError(elementId, message) { $(`#${elementId}`).text(message).addClass('show'); } /** * Скрытие ошибки */ hideError(elementId) { $(`#${elementId}`).removeClass('show').text(''); } /** * Отключение стандартной валидации браузера */ disableBrowserValidation() { // Принудительно убираем красную обводку с необязательных полей при загрузке $('#kpp, #okpo').css({ 'border-color': '#d1d5db', 'box-shadow': 'none', 'outline': 'none' }); // Отключаем стандартную валидацию для необязательных полей $('#kpp, #okpo').on('invalid', function(e) { e.preventDefault(); $(this).removeClass('error'); $(this).css({ 'border-color': '#d1d5db', 'box-shadow': 'none', 'outline': 'none' }); }); // Принудительно убираем красную обводку с необязательных полей при любом событии $('#kpp, #okpo').on('blur focus input change', function() { $(this).removeClass('error'); $(this).css({ 'border-color': '#d1d5db', 'box-shadow': 'none', 'outline': 'none' }); }); // Периодически проверяем и убираем красную обводку setInterval(() => { $('#kpp, #okpo').css({ 'border-color': '#d1d5db', 'box-shadow': 'none', 'outline': 'none' }); }, 100); } /** * Обработчики для скрытия ошибок при вводе */ initErrorHandlers() { // Список всех полей с их error ID const fieldErrorMap = { 'contact_name': 'contact_name-error', 'surname': 'surname-error', 'phone': 'phone-error', 'email': 'email-error', 'organization_name': 'organization_name-error', 'legal_address': 'legal_address-error', 'inn': 'inn-error', 'kpp': 'kpp-error', 'ogrn': 'ogrn-error', 'okpo': 'okpo-error', 'bik': 'bik-error', 'bank_name': 'bank_name-error', 'correspondent_account': 'correspondent_account-error', 'settlement_account': 'settlement_account-error', 'delivery_city': 'delivery_city-error', 'delivery_street': 'delivery_street-error', 'delivery_house': 'delivery_house-error' }; // Добавляем обработчики для каждого поля Object.keys(fieldErrorMap).forEach(fieldId => { $(`#${fieldId}`).on('input focus', () => { this.hideError(fieldErrorMap[fieldId]); }); }); } /** * Инициализация обработчиков сворачивания блока организации */ initOrgCollapseHandlers() { // Обработчик клика на заголовок блока организации $(document).on('click', '.org-section-header', () => { this.toggleOrgSection(); }); } /** * Переключение сворачивания/разворачивания блока организации */ toggleOrgSection() { const $orgSection = $('#organization-section'); const $orgContent = $('#org-section-content'); if ($orgSection.hasClass('collapsed')) { // Разворачиваем $orgSection.removeClass('collapsed'); $orgContent.slideDown(300); } else { // Сворачиваем $orgSection.addClass('collapsed'); $orgContent.slideUp(300); } } /** * Установка названия организации в заголовок блока */ setOrgSectionName(orgName) { const $orgName = $('#org-section-name'); const $orgTitle = $('.org-section-title'); if (orgName) { $orgName.text(` - ${orgName}`).show(); $orgTitle.text('Данные организации'); } else { $orgName.hide(); $orgTitle.text('Данные организации'); } } /** * Установка названия организации в статус клиента */ setStatusOrgName(orgName) { const $statusOrgName = $('#status-org-name'); if (orgName) { $statusOrgName.text(` "${orgName}"`).show(); } else { $statusOrgName.hide(); } } /** * Сворачивание блока организации для зарегистрированных юр.лиц */ collapseOrgSectionForAuthUser() { if (this.clientState.clientType === 'juridical') { const $orgSection = $('#organization-section'); $orgSection.addClass('collapsed'); $('#org-section-content').hide(); } } /** * Показ уведомления */ showNotification(message, type = 'info') { const notification = $(`
${message}
`); $('#widget-notifications').append(notification); // Автоматически скрываем через 5 секунд setTimeout(() => { notification.fadeOut(() => notification.remove()); }, 5000); } /** * Проверка заполненности обязательных полей организации и разворачивание блока */ checkOrgFieldsAndExpand() { const requiredFields = [ 'organization_name', 'legal_address', 'inn', 'ogrn', 'bik', 'bank_name', 'correspondent_account', 'settlement_account' ]; // Проверяем, есть ли пустые обязательные поля let hasEmptyFields = false; for (const fieldId of requiredFields) { const value = $(`#${fieldId}`).val(); if (!value || value.trim() === '') { hasEmptyFields = true; break; } } // Если есть пустые поля, разворачиваем блок организации if (hasEmptyFields) { const $orgSection = $('#organization-section'); $orgSection.removeClass('collapsed'); $('#org-section-content').show(); // Показываем уведомление this.showNotification('Заполните недостающие данные организации для оформления заказа', 'info'); } } /** * Получение данных организации по ИНН через DaData API * * ИНСТРУКЦИЯ ПО НАСТРОЙКЕ: * 1. Зарегистрируйтесь на https://dadata.ru * 2. Получите API ключ в личном кабинете * 3. Замените 'YOUR_DADATA_API_KEY' на ваш реальный ключ * 4. Бесплатный тариф: 100 запросов в сутки */ async fetchCompanyDataByINN(inn) { try { // Очищаем ИНН от лишних символов const cleanINN = inn.replace(/\D/g, ''); if (cleanINN.length !== 10 && cleanINN.length !== 12) { throw new Error('ИНН должен содержать 10 или 12 цифр'); } // Показываем индикатор загрузки this.showFieldLoading('inn', true); // Запрос к DaData API const response = await fetch('https://suggestions.dadata.ru/suggestions/api/4_1/rs/findById/party', { method: 'POST', headers: { 'Content-Type': 'application/json', 'Authorization': 'Token da92b4f24405aa61c91ead2726c34a99f965376a', 'Accept': 'application/json' }, body: JSON.stringify({ query: cleanINN }) }); if (!response.ok) { throw new Error('Ошибка при запросе к DaData API'); } const data = await response.json(); if (data.suggestions && data.suggestions.length > 0) { const company = data.suggestions[0].data; // Заполняем поля организации (используем краткое название) $('#organization_name').val(company.name?.short_with_opf || company.name?.full_with_opf || ''); // Полный юридический адрес - собираем из всех доступных частей let fullAddress = ''; // Сначала пробуем получить полный адрес с индексом if (company.address?.unrestricted_value) { fullAddress = company.address.unrestricted_value; } else if (company.address?.data?.source) { fullAddress = company.address.data.source; } else if (company.address?.value) { fullAddress = company.address.value; } else { // Собираем адрес из частей const parts = []; if (company.address?.data?.postal_code) parts.push(company.address.data.postal_code); if (company.address?.data?.region) parts.push(company.address.data.region); if (company.address?.data?.city) parts.push(company.address.data.city); if (company.address?.data?.street) parts.push(company.address.data.street); if (company.address?.data?.house) parts.push(company.address.data.house); if (company.address?.data?.flat) parts.push('кв. ' + company.address.data.flat); fullAddress = parts.join(', '); } // Для ИП адрес может быть только город - это нормально $('#legal_address').val(fullAddress); $('#ogrn').val(company.ogrn || ''); $('#okpo').val(company.okpo || ''); // КПП всегда заполняем, если есть if (company.kpp) { $('#kpp').val(company.kpp); } else { // Если КПП нет в данных, оставляем поле пустым $('#kpp').val(''); // Для ИП добавляем подсказку, что КПП не нужен if (company.type === 'INDIVIDUAL') { $('#kpp').attr('placeholder', 'КПП не требуется для ИП'); } } // Делаем поля readonly после автозаполнения this.setFieldsReadonly(['organization_name', 'legal_address', 'ogrn', 'okpo', 'kpp'], true); // Принудительно сбрасываем стили для проблемных полей setTimeout(() => { $('#kpp, #okpo').css({ 'border': '2px solid #e1e5e9', 'box-shadow': 'none', 'outline': 'none' }); }, 100); this.showNotification('Данные организации загружены автоматически', 'success'); } else { throw new Error('Организация с таким ИНН не найдена'); } } catch (error) { this.showNotification(`Ошибка загрузки данных: ${error.message}`, 'error'); } finally { this.showFieldLoading('inn', false); } } /** * Получение банковских данных по БИК через DaData API * * ИНСТРУКЦИЯ ПО НАСТРОЙКЕ: * 1. Используйте тот же API ключ, что и для организаций * 2. Замените 'YOUR_DADATA_API_KEY' на ваш реальный ключ * 3. Бесплатный тариф: 100 запросов в сутки */ async fetchBankDataByBIK(bik) { try { // Очищаем БИК от лишних символов const cleanBIK = bik.replace(/\D/g, ''); if (cleanBIK.length !== 9) { throw new Error('БИК должен содержать 9 цифр'); } // Показываем индикатор загрузки this.showFieldLoading('bik', true); // Запрос к DaData API для банков const response = await fetch('https://suggestions.dadata.ru/suggestions/api/4_1/rs/findById/bank', { method: 'POST', headers: { 'Content-Type': 'application/json', 'Authorization': 'Token da92b4f24405aa61c91ead2726c34a99f965376a', 'Accept': 'application/json' }, body: JSON.stringify({ query: cleanBIK }) }); if (!response.ok) { throw new Error('Ошибка при запросе к DaData API'); } const data = await response.json(); if (data.suggestions && data.suggestions.length > 0) { const bank = data.suggestions[0].data; // Заполняем банковские поля $('#bank_name').val(bank.name?.payment || bank.name?.full || ''); if (bank.correspondent_account) { $('#correspondent_account').val(bank.correspondent_account); } // Делаем поля readonly после автозаполнения this.setFieldsReadonly(['bank_name', 'correspondent_account'], true); this.showNotification('Банковские данные загружены автоматически', 'success'); } else { throw new Error('Банк с таким БИК не найден'); } } catch (error) { this.showNotification(`Ошибка загрузки банковских данных: ${error.message}`, 'error'); } finally { this.showFieldLoading('bik', false); } } /** * Показать/скрыть индикатор загрузки для поля */ showFieldLoading(fieldId, show) { const $field = $(`#${fieldId}`); const $loading = $field.siblings('.field-loading'); if (show) { if ($loading.length === 0) { $field.after('
⏳ Загрузка...
'); } $field.prop('disabled', true); } else { $loading.remove(); $field.prop('disabled', false); } } /** * Установить поля в режим readonly */ setFieldsReadonly(fieldIds, readonly) { fieldIds.forEach(fieldId => { const $field = $(`#${fieldId}`); $field.prop('readonly', readonly); if (readonly) { $field.addClass('auto-filled'); } else { $field.removeClass('auto-filled'); } }); } /** * Инициализация обработчика сообщений о промокодах */ initCouponMessageHandler() { // Флаг для предотвращения повторной обработки let isProcessing = false; // Следим только за изменениями в DOM const observer = new MutationObserver((mutations) => { if (isProcessing) return; mutations.forEach((mutation) => { if (mutation.type === 'childList') { mutation.addedNodes.forEach((node) => { if (node.nodeType === 1) { // Element node const $node = $(node); // Проверяем только точное сообщение о регистрации const text = $node.text().trim(); if (text === 'Для использования купона необходимо зарегистрироваться') { isProcessing = true; const isUnauthorized = !this.clientState.isAuthorized; const isAuthorizedButUnregistered = this.clientState.isAuthorized && !this.clientState.isRegistered; if (isUnauthorized || isAuthorizedButUnregistered) { $node.replaceWith(this.createCouponSuccessMessage()); } setTimeout(() => { isProcessing = false; }, 100); } // Проверяем вложенные элементы $node.find('*').each((index, element) => { const $element = $(element); const text = $element.text().trim(); if (text === 'Для использования купона необходимо зарегистрироваться') { isProcessing = true; const isUnauthorized = !this.clientState.isAuthorized; const isAuthorizedButUnregistered = this.clientState.isAuthorized && !this.clientState.isRegistered; if (isUnauthorized || isAuthorizedButUnregistered) { $element.replaceWith(this.createCouponSuccessMessage()); } setTimeout(() => { isProcessing = false; }, 100); } }); } }); } }); }); // Начинаем наблюдение за изменениями в DOM observer.observe(document.body, { childList: true, subtree: true }); // Перехватываем через наш метод showNotification const originalShowNotification = this.showNotification; this.showNotification = (message, type) => { if (message === 'Для использования купона необходимо зарегистрироваться') { const isUnauthorized = !this.clientState.isAuthorized; const isAuthorizedButUnregistered = this.clientState.isAuthorized && !this.clientState.isRegistered; if (isUnauthorized || isAuthorizedButUnregistered) { this.showCouponSuccessMessage(); return; } } originalShowNotification.call(this, message, type); }; } /** * Создать элемент сообщения об успешном применении промокода */ createCouponSuccessMessage() { return $(`
Промокод будет применен при оформлении заказа
`); } /** * Скрыть предупреждения InSales в консоли */ hideConsoleWarnings() { // Перехватываем console.warn для скрытия предупреждений о купонах const originalWarn = console.warn; console.warn = function(...args) { const message = args.join(' '); // Скрываем предупреждения о купонах if (message.includes('Вы отключили атвоматическое обновление страницы корзины после применения купона') || message.includes('set_coupon:insales:cart')) { return; // Не выводим это сообщение } // Для всех остальных сообщений используем оригинальный warn originalWarn.apply(console, args); }; } /** * Показать сообщение об успешном применении промокода */ showCouponSuccessMessage() { // Удаляем предыдущие сообщения о промокоде $('.coupon-success-message').remove(); // Создаем новое сообщение const $message = this.createCouponSuccessMessage(); // Ищем поле промокода и добавляем сообщение после него const $couponField = $('input[name="coupon_code"], input[name="coupon"], input[placeholder*="промокод"], input[placeholder*="Промокод"]'); if ($couponField.length > 0) { $couponField.after($message); } else { // Если поле не найдено, добавляем в конец формы $('.widget-main').append($message); } // Автоматически скрываем сообщение через 5 секунд setTimeout(() => { $message.fadeOut(300, function() { $(this).remove(); }); }, 5000); } } // Глобальная обработка ошибок для предотвращения поломки сайта window.addEventListener('error', function(event) { console.error('UNIFIED_WIDGET_V3: Глобальная ошибка JavaScript:', event.error); // Предотвращаем поломку сайта из-за внешних ошибок event.preventDefault(); }); // Обработка неправильных ссылок на изображения $(document).ready(function() { // Исправляем неправильные ссылки на изображения $('img[src*="${item.image}"]').each(function() { $(this).attr('src', '').hide(); console.warn('UNIFIED_WIDGET_V3: Исправлена неправильная ссылка на изображение'); }); }); // Инициализация виджета при загрузке DOM $(document).ready(function() { try { window.unifiedWidget = new UnifiedWidgetV3(); } catch (error) { console.error('UNIFIED_WIDGET_V3: Ошибка инициализации виджета:', error); } }); } catch(error) { console.error('Widget "widget-type_CART_ONLY"', error) } } catch(error) { console.error('Widget "widget-type_CART_ONLY"', error) }