dev_gp | fix: перенесен калькулятор и php_interface

master
Andrei 2 months ago
parent 432d45208b
commit 416955477b
  1. 265
      local/components/era/calculator/class.php
  2. 56
      local/components/era/calculator/templates/.default/ajax.php
  3. 383
      local/components/era/calculator/templates/.default/template.php
  4. 11
      local/components/era/html.map/.description.php
  5. 6
      local/components/era/html.map/.parameters.php
  6. 25
      local/components/era/html.map/class.php
  7. 25
      local/components/era/html.map/templates/.default/template.php
  8. 5
      local/php_interface/include/components/bitrix/news/services/.description.php
  9. 43
      local/php_interface/include/components/bitrix/news/services/style.css
  10. 21
      local/php_interface/include/components/bitrix/news/services/template.php
  11. 126
      local/php_interface/include/events.php

@ -0,0 +1,265 @@
<?php
if (!defined("B_PROLOG_INCLUDED") || B_PROLOG_INCLUDED !== true) die();
use Bitrix\Main\Loader;
use Bitrix\Iblock\ElementTable;
class EraCalculatorComponent extends CBitrixComponent
{
private $iblockId;
private $isAjax = false;
public function onPrepareComponentParams($arParams)
{
$this->iblockId = $arParams['IBLOCK_ID'];
// Добавляем параметры для работы с ценами
if (!isset($arParams['PRICE_CODE']))
$arParams['PRICE_CODE'] = array();
if (!isset($arParams['PRICE_VAT_INCLUDE']))
$arParams['PRICE_VAT_INCLUDE'] = 'Y';
if (!isset($arParams['CONVERT_CURRENCY']))
$arParams['CONVERT_CURRENCY'] = 'N';
if (!isset($arParams['CURRENCY_ID']))
$arParams['CURRENCY_ID'] = '';
return $arParams;
}
public function executeComponent()
{
if (!Loader::includeModule('iblock')) {
ShowError('Модуль iblock не установлен');
return;
}
if (!Loader::includeModule('catalog')) {
ShowError('Модуль catalog не установлен');
return;
}
// Проверяем, является ли запрос AJAX
$this->isAjax = $this->request->get('ajax') === 'Y';
// Получаем все значения для почвы
$this->arResult['SOIL_TYPES'] = $this->getPropertyEnumValues(58);
// Получаем все значения для количества человек
$this->arResult['PEOPLE_COUNT'] = $this->getPropertyEnumValues(28);
// Получаем значения для типа проживания
$this->arResult['LIVING_TYPES'] = $this->getPropertyEnumValues(61);
// Получаем значения для грунтовых вод
$this->arResult['GROUND_WATER'] = $this->getPropertyEnumValues(57);
if ($this->request->isPost() && ($this->request->getPost('calculate') === 'Y' || $this->isAjax)) {
$this->processCalculation();
}
if ($this->isAjax) {
$this->sendAjaxResponse();
} else {
$this->includeComponentTemplate();
}
}
private function getPropertyEnumValues($propertyId)
{
$result = [];
$property_enums = CIBlockPropertyEnum::GetList(
["SORT" => "ASC"],
["PROPERTY_ID" => $propertyId]
);
while($enum_fields = $property_enums->GetNext()) {
$result[$enum_fields["XML_ID"]] = [
'ID' => $enum_fields["ID"],
'NAME' => $enum_fields["VALUE"],
'XML_ID' => $enum_fields["XML_ID"]
];
}
return $result;
}
private function calculateInstallationPrice($volume)
{
// Базовая стоимость установки
$basePrice = 35000;
// Увеличиваем стоимость в зависимости от объема
$priceIncrease = floor($volume / 50) * 5000;
$minPrice = $basePrice + $priceIncrease;
$maxPrice = $minPrice + 10000;
return number_format($minPrice, 0, '.', ' ') . ' ₽ - ' . number_format($maxPrice, 0, '.', ' ') . ' ₽';
}
private function calculateVolume($request)
{
$totalVolume = 0;
// Массив объемов для каждого прибора
$volumes = [
'bath' => 200,
'toilet' => 10,
'sink' => 20,
'shower' => 50,
'bidet' => 10,
'jacuzzi' => 400,
'washer' => 50,
'dishwasher' => 50
];
// Проходим по каждому прибору
foreach ($volumes as $device => $volume) {
// Проверяем, включен ли прибор
if ($request->get($device) === 'Y') {
// Получаем количество приборов (1, 2 или 3)
$count = (int)$request->get($device . '_count');
if ($count > 0 && $count <= 3) {
$totalVolume += $volume * $count;
}
}
}
return $totalVolume;
}
private function processCalculation()
{
$request = $this->request->getPostList();
// Логируем все пришедшие данные
AddMessage2Log(print_r($request->toArray(), true), 'CALC_LOG: REQUEST');
// Получаем объем из POST
$volume = (int)$request->get('volume');
if ($volume <= 0) {
$volume = $this->calculateVolume($request); // fallback
}
// Логируем рассчитанный объем
AddMessage2Log('Calculated volume: ' . $volume, 'CALC_LOG: VOLUME');
$soil = $request->get('soil');
$people = $request->get('people');
$living = $request->get('living');
$ground_water = $request->get('ground_water');
// Формируем фильтр для выборки товаров
$filter = [
'IBLOCK_ID' => $this->iblockId,
'ACTIVE' => 'Y'
];
// Добавляем фильтр по почве если выбрано
if ($soil && isset($this->arResult['SOIL_TYPES'][$soil])) {
$filter['PROPERTY_58'] = $this->arResult['SOIL_TYPES'][$soil]['ID'];
}
// Добавляем фильтр по количеству человек если выбрано
if ($people && isset($this->arResult['PEOPLE_COUNT'][$people])) {
$filter['PROPERTY_28'] = $this->arResult['PEOPLE_COUNT'][$people]['ID'];
}
// Добавляем фильтр по типу проживания если выбрано
if ($living && isset($this->arResult['LIVING_TYPES'][$living])) {
$filter['PROPERTY_61'] = $this->arResult['LIVING_TYPES'][$living]['ID'];
}
// Добавляем фильтр по грунтовым водам если выбрано
if ($ground_water && isset($this->arResult['GROUND_WATER'][$ground_water])) {
$filter['PROPERTY_57'] = $this->arResult['GROUND_WATER'][$ground_water]['ID'];
}
// Логируем итоговый фильтр
AddMessage2Log(print_r($filter, true), 'CALC_LOG: FILTER');
// Добавляем фильтр по залповому сбросу
if ($volume > 0) {
$filter['>PROPERTY_SBROS_NUM'] = $volume;
}
// Получаем товары
$elements = CIBlockElement::GetList(
['SORT' => 'ASC'],
$filter,
false,
['nPageSize' => 3],
['*', 'PROPERTY_*']
);
$this->arResult['ITEMS'] = [];
$prices = [];
while ($element = $elements->GetNextElement()) {
$fields = $element->GetFields();
$properties = $element->GetProperties();
// Получаем все картинки
if($fields['PREVIEW_PICTURE']) {
$fields['PREVIEW_PICTURE'] = CFile::GetPath($fields['PREVIEW_PICTURE']);
}
// Формируем массив с полной информацией о товаре
$item = [
'ID' => $fields['ID'],
'NAME' => $fields['NAME'],
'PREVIEW_PICTURE' => $fields['PREVIEW_PICTURE'],
'PREVIEW_TEXT' => $fields['PREVIEW_TEXT'],
'DETAIL_PAGE_URL' => $fields['DETAIL_PAGE_URL'],
'PRICE' => $properties['ATT_OLD_PRICE']['VALUE'],
'PEOPLE_COUNT' => $properties['PEOPLE_COUNT']['VALUE'],
'PERFORMANCE' => $properties['PERFORMANCE']['VALUE'],
'RESET' => $properties['SBROS_NUM']['VALUE'],
'POWER' => $properties['POWER']['VALUE'],
'RATING' => $properties['REV_RATING']['VALUE'][0]
];
// Добавляем цену в массив цен для расчета диапазона
if (!empty($item['PRICE'])) {
$prices[] = (float)$item['PRICE'];
}
$this->arResult['ITEMS'][] = $item;
}
// Логируем найденные товары
AddMessage2Log(print_r($this->arResult['ITEMS'], true), 'CALC_LOG: ITEMS');
// Устанавливаем диапазон цен из найденных товаров
if (!empty($prices)) {
$minPrice = min($prices);
$maxPrice = max($prices);
$this->arResult['INSTALLATION_PRICE'] = number_format($minPrice, 0, '.', ' ') . ' ₽ - ' . number_format($maxPrice, 0, '.', ' ') . ' ₽';
} else {
$this->arResult['INSTALLATION_PRICE'] = 'Цена по запросу';
}
return true;
}
private function sendAjaxResponse()
{
global $APPLICATION;
$APPLICATION->RestartBuffer();
// Получаем HTML для товаров
ob_start();
$this->includeComponentTemplate('ajax');
$itemsHtml = ob_get_clean();
$response = [
'items' => $itemsHtml,
'installation_price' => $this->arResult['INSTALLATION_PRICE']
];
echo json_encode($response);
die();
}
}

@ -0,0 +1,56 @@
<?php if (!defined("B_PROLOG_INCLUDED") || B_PROLOG_INCLUDED !== true) die();
/** @var array $arParams */
/** @var array $arResult */
if (!empty($arResult['ITEMS'])):
foreach ($arResult['ITEMS'] as $item): ?>
<div class="product">
<a class="product__image" href="<?=$item['DETAIL_PAGE_URL']?>">
<img src="<?=$item['PREVIEW_PICTURE']?>" alt="<?=$item['NAME']?>">
</a>
<div class="product__data">
<?php if(isset($item['RATING'])): ?>
<div class="product__rating rating rating--<?=$item['RATING']?>"><?=$item['RATING']?>/5</div>
<?php endif; ?>
<div class="product__info">
<a class="product__title" href="<?=$item['DETAIL_PAGE_URL']?>"><?=$item['NAME']?></a>
<?php if(!empty($item['PREVIEW_TEXT'])): ?>
<p class="product__text"><?=$item['PREVIEW_TEXT']?></p>
<?php endif; ?>
</div>
<div class="product__info">
<?php if(!empty($item['PEOPLE_COUNT'])): ?>
<p class="product__text">Пользователей: <span><?=$item['PEOPLE_COUNT']?></span></p>
<?php endif; ?>
<?php if(!empty($item['PERFORMANCE'])): ?>
<p class="product__text">Производительность: <span><?=$item['PERFORMANCE']?> м³/сут</span></p>
<?php endif; ?>
<?php if(!empty($item['RESET'])): ?>
<p class="product__text">Залповый сброс: <span><?=$item['RESET']?> л</span></p>
<?php endif; ?>
<?php if(!empty($item['POWER'])): ?>
<p class="product__text">Питание: <span><?=$item['POWER']?></span></p>
<?php endif; ?>
</div>
<?php if(!empty($item['PRICE'])): ?>
<div class="product__price"><?=number_format($item['PRICE'], 0, '.', ' ')?></div>
<?php endif; ?>
<div class="product__btns">
<button class="button button--orange" onclick="addToCart(<?=$item['ID']?>)">Купить</button>
<button class="button button--outline">Купить с установкой</button>
</div>
</div>
</div>
<?php endforeach;
else: ?>
<div class="product__order">
<h3 class="product__order-title section-title">Нужен септик для бизнеса?</h3>
<div class="product__order-info">Наш менеджер свяжется с вами в ближайшее время</div>
<form action="#">
<input type="text" class="input" placeholder="Ваше имя">
<input type="tel" class="input" placeholder="Номер телефона">
<button class="button button--orange" type="submit">Заказать звонок</button>
<div class="product__order-sub">Нажимая кнопку «Заказать звонок», вы подтверждаете свое согласие на обработку <a href="#">персональных данных</a></div>
</form>
</div>
<?php endif; ?>

@ -0,0 +1,383 @@
<?php if (!defined("B_PROLOG_INCLUDED") || B_PROLOG_INCLUDED !== true) die();
/** @var array $arParams */
/** @var array $arResult */
/** @global CMain $APPLICATION */
/** @global CUser $USER */
/** @global CDatabase $DB */
/** @var CBitrixComponentTemplate $this */
/** @var string $templateName */
/** @var string $templateFile */
/** @var string $templateFolder */
/** @var string $componentPath */
/** @var CBitrixComponent $component */
?>
<section class="calc section-inner container">
<h1 class="calc__title">Рассчитать септик онлайн</h1>
<form action="" method="POST" id="calculator-form">
<input type="hidden" name="calculate" value="Y">
<div class="calc__form">
<h2 class="calc__form-title">Участок, септик</h2>
<div class="calc__form-top">
<div class="select">
<div class="select__name">Почва</div>
<select name="soil" id="soil" class="js-calc-field">
<option value="">Выберите тип почвы</option>
<?php foreach ($arResult['SOIL_TYPES'] as $code => $soil): ?>
<option value="<?=$code?>"><?=$soil['NAME']?></option>
<?php endforeach; ?>
</select>
</div>
<div class="select">
<div class="select__name">Количество людей</div>
<select name="people" id="people" class="js-calc-field">
<option value="">Выберите количество человек</option>
<?php foreach ($arResult['PEOPLE_COUNT'] as $code => $people): ?>
<option value="<?=$code?>"><?=$people['NAME']?></option>
<?php endforeach; ?>
</select>
</div>
<div class="select">
<div class="select__name">Проживание</div>
<select name="living" id="living" class="js-calc-field">
<option value="">Выберите тип проживания</option>
<?php foreach ($arResult['LIVING_TYPES'] as $code => $type): ?>
<option value="<?=$code?>"><?=$type['NAME']?></option>
<?php endforeach; ?>
</select>
</div>
<div class="select">
<div class="select__name">Глубина залегания труб</div>
<select name="ground_water" id="ground_water" class="js-calc-field">
<option value="">Выберите уровень грунтовых вод</option>
<?php foreach ($arResult['GROUND_WATER'] as $code => $water): ?>
<option value="<?=$code?>"><?=$water['NAME']?></option>
<?php endforeach; ?>
</select>
</div>
</div>
<div class="calc__top-item">
<input class="visually-hidden" type="checkbox" name="with_ground_water" id="ground_water_check">
<label class="switcher" for="ground_water_check">Высокие грунтовые воды</label>
</div>
</div>
<div class="calc__form">
<h2 class="calc__form-title">Залповый сброс</h2>
<div class="calc__form-bottom">
<div class="calc__form-groups">
<div class="calc__group">
<div class="calc__switcher">
<input class="visually-hidden" type="checkbox" name="bath" id="calc-bath">
<label class="switcher" for="calc-bath">Ванна, 200л</label>
</div>
<div class="calc__radios">
<input class="visually-hidden" type="radio" name="bath" value="1" id="bath-1" checked>
<label class="radio" for="bath-1">1</label>
<input class="visually-hidden" type="radio" name="bath" value="2" id="bath-2">
<label class="radio" for="bath-2">2</label>
<input class="visually-hidden" type="radio" name="bath" value="3" id="bath-3">
<label class="radio" for="bath-3">3</label>
</div>
</div>
<div class="calc__group">
<div class="calc__switcher">
<input class="visually-hidden" type="checkbox" name="toilet" id="calc-toilet">
<label class="switcher" for="calc-toilet">Унитаз, 10л</label>
</div>
<div class="calc__radios">
<input class="visually-hidden" type="radio" name="toilet" value="1" id="toilet-1" checked>
<label class="radio" for="toilet-1">1</label>
<input class="visually-hidden" type="radio" name="toilet" value="2" id="toilet-2">
<label class="radio" for="toilet-2">2</label>
<input class="visually-hidden" type="radio" name="toilet" value="3" id="toilet-3">
<label class="radio" for="toilet-3">3</label>
</div>
</div>
<div class="calc__group">
<div class="calc__switcher">
<input class="visually-hidden" type="checkbox" name="sink" id="calc-sink">
<label class="switcher" for="calc-sink">Раковина, 20л</label>
</div>
<div class="calc__radios">
<input class="visually-hidden" type="radio" name="sink" value="1" id="sink-1" checked>
<label class="radio" for="sink-1">1</label>
<input class="visually-hidden" type="radio" name="sink" value="2" id="sink-2">
<label class="radio" for="sink-2">2</label>
<input class="visually-hidden" type="radio" name="sink" value="3" id="sink-3">
<label class="radio" for="sink-3">3</label>
</div>
</div>
<div class="calc__group">
<div class="calc__switcher">
<input class="visually-hidden" type="checkbox" name="shower" id="calc-shower">
<label class="switcher" for="calc-shower">Душ, 50л</label>
</div>
<div class="calc__radios">
<input class="visually-hidden" type="radio" name="shower" value="1" id="shower-1" checked>
<label class="radio" for="shower-1">1</label>
<input class="visually-hidden" type="radio" name="shower" value="2" id="shower-2">
<label class="radio" for="shower-2">2</label>
<input class="visually-hidden" type="radio" name="shower" value="3" id="shower-3">
<label class="radio" for="shower-3">3</label>
</div>
</div>
<div class="calc__group">
<div class="calc__switcher">
<input class="visually-hidden" type="checkbox" name="bidet" id="calc-bidet">
<label class="switcher" for="calc-bidet">Биде, 10л</label>
</div>
<div class="calc__radios">
<input class="visually-hidden" type="radio" name="bidet" value="1" id="bidet-1" checked>
<label class="radio" for="bidet-1">1</label>
<input class="visually-hidden" type="radio" name="bidet" value="2" id="bidet-2">
<label class="radio" for="bidet-2">2</label>
<input class="visually-hidden" type="radio" name="bidet" value="3" id="bidet-3">
<label class="radio" for="bidet-3">3</label>
</div>
</div>
<div class="calc__group">
<div class="calc__switcher">
<input class="visually-hidden" type="checkbox" name="jacuzzi" id="calc-jacuzzi">
<label class="switcher" for="calc-jacuzzi">Джакузи, 400л</label>
</div>
<div class="calc__radios">
<input class="visually-hidden" type="radio" name="jacuzzi" value="1" id="jacuzzi-1" checked>
<label class="radio" for="jacuzzi-1">1</label>
<input class="visually-hidden" type="radio" name="jacuzzi" value="2" id="jacuzzi-2">
<label class="radio" for="jacuzzi-2">2</label>
<input class="visually-hidden" type="radio" name="jacuzzi" value="3" id="jacuzzi-3">
<label class="radio" for="jacuzzi-3">3</label>
</div>
</div>
<div class="calc__group">
<div class="calc__switcher">
<input class="visually-hidden" type="checkbox" name="washer" id="calc-washer">
<label class="switcher" for="calc-washer">Стиральная машина, 50л</label>
</div>
<div class="calc__radios">
<input class="visually-hidden" type="radio" name="washer" value="1" id="washer-1" checked>
<label class="radio" for="washer-1">1</label>
<input class="visually-hidden" type="radio" name="washer" value="2" id="washer-2">
<label class="radio" for="washer-2">2</label>
<input class="visually-hidden" type="radio" name="washer" value="3" id="washer-3">
<label class="radio" for="washer-3">3</label>
</div>
</div>
<div class="calc__group">
<div class="calc__switcher">
<input class="visually-hidden" type="checkbox" name="dishwasher" id="calc-dishwasher">
<label class="switcher" for="calc-dishwasher">Посудомойка, 50л</label>
</div>
<div class="calc__radios">
<input class="visually-hidden" type="radio" name="dishwasher" value="1" id="dishwasher-1" checked>
<label class="radio" for="dishwasher-1">1</label>
<input class="visually-hidden" type="radio" name="dishwasher" value="2" id="dishwasher-2">
<label class="radio" for="dishwasher-2">2</label>
<input class="visually-hidden" type="radio" name="dishwasher" value="3" id="dishwasher-3">
<label class="radio" for="dishwasher-3">3</label>
</div>
</div>
</div>
<div class="calc__sum">
<h3 class="calc__sum-title">Примерная стоимость монтажа</h3>
<div class="calc__sum-price" id="installation-price">
<?=$arResult['INSTALLATION_PRICE_MIN']?> ₽ - <?=$arResult['INSTALLATION_PRICE_MAX']?>
</div>
<div class="calc__sum-desc">Точную цену можно узнать после консультации</div>
<button class="button button--orange" type="button" data-action="order-install">Заказать монтаж</button>
</div>
</div>
<div class="calc__actions">
<button type="submit" class="button button--orange">Рассчитать</button>
</div>
</div>
</form>
</section>
<section class="sale sale--calc section-inner container" id="calculator-container" style="display: none;">
<h2 class="section-title">Подходящие септики в нашем каталоге</h2>
<div class="sale__wrap">
<div class="sale__products" id="calculator-results">
<?php if (!empty($arResult['ITEMS'])): ?>
<?php foreach ($arResult['ITEMS'] as $item): ?>
<div class="product">
<pre style="background: #f5f5f5; padding: 10px; overflow: auto; max-height: 300px;">
<?php print_r($item); ?>
</pre>
<a class="product__image" href="<?=$item['DETAIL_PAGE_URL']?>">
<img src="<?=$item['PREVIEW_PICTURE']?>" alt="<?=$item['NAME']?>">
</a>
<div class="product__data">
<?php if(isset($item['RATING'])): ?>
<div class="product__rating rating rating--<?=$item['RATING']?>"><?=$item['RATING']?>/5</div>
<?php endif; ?>
<div class="product__info">
<a class="product__title" href="<?=$item['DETAIL_PAGE_URL']?>"><?=$item['NAME']?></a>
<?php if(!empty($item['PREVIEW_TEXT'])): ?>
<p class="product__text"><?=$item['PREVIEW_TEXT']?></p>
<?php endif; ?>
</div>
<div class="product__info">
<?php if(!empty($item['PEOPLE_COUNT'])): ?>
<p class="product__text">Пользователей: <span><?=$item['PEOPLE_COUNT']?></span></p>
<?php endif; ?>
<?php if(!empty($item['PERFORMANCE'])): ?>
<p class="product__text">Производительность: <span><?=$item['PERFORMANCE']?> м³/сут</span></p>
<?php endif; ?>
<?php if(!empty($item['RESET'])): ?>
<p class="product__text">Залповый сброс: <span><?=$item['RESET']?> л</span></p>
<?php endif; ?>
<?php if(!empty($item['POWER'])): ?>
<p class="product__text">Питание: <span><?=$item['POWER']?></span></p>
<?php endif; ?>
</div>
<?php if(!empty($item['PRICE'])): ?>
<div class="product__price"><?=number_format($item['PRICE'], 0, '.', ' ')?></div>
<?php endif; ?>
<div class="product__btns">
<button class="button button--orange" onclick="addToCart(<?=$item['ID']?>)">Купить</button>
<button class="button button--outline">Купить с установкой</button>
</div>
<?php if(!empty($item['REVIEWS'])): ?>
<div class="product__reviews">
<h3>Отзывы:</h3>
<?php foreach($item['REVIEWS'] as $review): ?>
<div class="review">
<div class="review__header">
<span class="review__author"><?=$review['NAME']?></span>
<span class="review__city"><?=$review['CITY']?></span>
<span class="review__date"><?=$review['DATE']?></span>
<span class="review__rating"><?=$review['RATING']?>/5</span>
</div>
<div class="review__content">
<h4><?=$review['HEADER']?></h4>
<p><?=$review['TEXT']?></p>
</div>
</div>
<?php endforeach; ?>
</div>
<?php endif; ?>
</div>
</div>
<?php endforeach; ?>
<?php endif; ?>
</div>
</div>
</section>
<script>
document.addEventListener('DOMContentLoaded', function() {
const form = document.getElementById('calculator-form');
const resultsContainer = document.getElementById('calculator-results');
const calculatorContainer = document.getElementById('calculator-container');
function validateForm() {
const selects = form.querySelectorAll('select');
for (let select of selects) {
if (select.name === 'ground_water') continue;
if (!select.value) {
alert('Пожалуйста, заполните все поля');
return false;
}
}
return true;
}
function updateResults(e) {
e.preventDefault();
if (!validateForm()) {
return;
}
// Считаем объем только по отмеченным чекбоксам
const deviceVolumes = {
bath: 200,
toilet: 10,
sink: 20,
shower: 50,
bidet: 10,
jacuzzi: 400,
washer: 50,
dishwasher: 50
};
let totalVolume = 0;
const devices = Object.keys(deviceVolumes);
devices.forEach(device => {
const checkbox = document.getElementById(`calc-${device}`);
if (checkbox && checkbox.checked) {
totalVolume += deviceVolumes[device];
}
});
// Собираем только нужные поля
const formData = new FormData();
formData.append('ajax', 'Y');
formData.append('calculate', 'Y');
formData.append('soil', document.getElementById('soil').value);
formData.append('people', document.getElementById('people').value);
formData.append('living', document.getElementById('living').value);
formData.append('ground_water', document.getElementById('ground_water').value);
formData.append('volume', totalVolume);
// Логи
console.log('Calculated total volume:', totalVolume);
console.log('--- FormData to send ---');
for (let pair of formData.entries()) {
console.log(pair[0]+ ': ' + pair[1]);
}
console.log('------------------------');
fetch('', {
method: 'POST',
body: formData
})
.then(response => response.json())
.then(data => {
if (data.items) {
calculatorContainer.style.display = 'block';
resultsContainer.innerHTML = data.items;
} else {
calculatorContainer.style.display = 'none';
}
if (data.installation_price) {
const priceElement = document.getElementById('installation-price');
if (priceElement) {
priceElement.textContent = data.installation_price;
}
}
})
.catch(error => {
console.error('Error:', error);
calculatorContainer.style.display = 'none';
});
}
// Добавляем обработчик отправки формы
form.addEventListener('submit', updateResults);
});
</script>
<style>
.calc__actions {
margin-top: 20px;
text-align: center;
}
.calc__actions .button {
min-width: 200px;
}
</style>

@ -0,0 +1,11 @@
<?php
if (!defined("B_PROLOG_INCLUDED") || B_PROLOG_INCLUDED!==true) die();
$arComponentDescription = array(
"NAME" => "HTML-карта сайта",
"DESCRIPTION" => "Автоматическая html-карта сайта с древовидной структурой.",
"ICON" => "",
"PATH" => array(
"ID" => "era"
),
);

@ -0,0 +1,6 @@
<?php
if (!defined("B_PROLOG_INCLUDED") || B_PROLOG_INCLUDED!==true) die();
$arComponentParameters = array(
"PARAMETERS" => array()
);

@ -0,0 +1,25 @@
<?php
if (!defined("B_PROLOG_INCLUDED") || B_PROLOG_INCLUDED!==true) die();
use Bitrix\Main\Loader;
use Bitrix\Iblock\SectionTable;
use Bitrix\Iblock\ElementTable;
class HtmlMapComponent extends CBitrixComponent
{
public function executeComponent()
{
// Получаем структуру сайта (разделы, фильтры)
$this->arResult['TREE'] = $this->getSiteTree();
$this->includeComponentTemplate();
}
private function getSiteTree()
{
// TODO: Реализовать сбор структуры сайта, разделов, фильтров
// Пример: получить разделы каталога
$tree = [];
// ...
return $tree;
}
}

@ -0,0 +1,25 @@
<?if(!defined("B_PROLOG_INCLUDED")||B_PROLOG_INCLUDED!==true)die(); ?>
<div class="html-map">
<h1>HTML-карта сайта</h1>
<?php if (!empty($arResult['TREE'])): ?>
<ul class="html-map__list">
<?php foreach ($arResult['TREE'] as $item): ?>
<li>
<a href="<?=$item['URL']?>"><?=$item['TITLE']?></a>
<?php if (!empty($item['CHILDREN'])): ?>
<ul>
<?php foreach ($item['CHILDREN'] as $child): ?>
<li>
<a href="<?=$child['URL']?>"><?=$child['TITLE']?></a>
<!-- и так далее, до 4 уровня -->
</li>
<?php endforeach; ?>
</ul>
<?php endif; ?>
</li>
<?php endforeach; ?>
</ul>
<?php else: ?>
<p>Карта сайта пуста.</p>
<?php endif; ?>
</div>

@ -0,0 +1,5 @@
<?
return array(
"NAME" => "Услуги (кастомный шаблон)",
"DESCRIPTION" => "Шаблон для компонента bitrix:news (услуги)",
);

@ -0,0 +1,43 @@
.services-list {
display: flex;
flex-wrap: wrap;
gap: 24px;
}
.service-item {
border: 1px solid #e0e0e0;
border-radius: 8px;
padding: 16px;
width: 300px;
box-shadow: 0 2px 8px rgba(0,0,0,0.04);
background: #fff;
display: flex;
flex-direction: column;
align-items: flex-start;
}
.service-item h2 {
font-size: 1.2em;
margin: 0 0 8px 0;
}
.service-item img {
max-width: 100%;
border-radius: 4px;
margin-bottom: 8px;
}
.service-desc {
margin-bottom: 8px;
color: #444;
}
.service-price {
font-weight: bold;
color: #1a7f37;
margin-bottom: 8px;
}
.service-item a {
margin-top: auto;
color: #1976d2;
text-decoration: none;
font-weight: 500;
}
.service-item a:hover {
text-decoration: underline;
}

@ -0,0 +1,21 @@
<?if(!defined("B_PROLOG_INCLUDED") || B_PROLOG_INCLUDED!==true)die();?>
<div class="services-list">
<?foreach(
$arResult["ITEMS"] as $arItem):?>
<div class="service-item">
<h2><?=$arItem["NAME"]?></h2>
<?if($arItem["PREVIEW_PICTURE"]):?>
<img src="<?=$arItem["PREVIEW_PICTURE"]["SRC"]?>" alt="<?=$arItem["NAME"]?>">
<?endif;?>
<div class="service-desc">
<?=$arItem["PREVIEW_TEXT"]?>
</div>
<?if($arItem["PROPERTIES"]["PRICE"]["VALUE"]):?>
<div class="service-price">
Цена: <?=$arItem["PROPERTIES"]["PRICE"]["VALUE"]?>
</div>
<?endif;?>
<a href="<?=$arItem["DETAIL_PAGE_URL"]?>">Подробнее</a>
</div>
<?endforeach;?>
</div>

@ -0,0 +1,126 @@
<?php
$eventType = new CEventType;
$eventMessage = new CEventMessage;
// Проверяем существование типа почтового события
$eventTypeResult = $eventType->GetList(array("TYPE_ID" => "CONSULTATION_REQUEST"));
if (!$eventTypeResult->Fetch()) {
// Создаем тип почтового события
$eventType->Add(array(
"EVENT_NAME" => "CONSULTATION_REQUEST",
"NAME" => "Заявка на консультацию",
"LID" => "ru",
"DESCRIPTION" => "#NAME# - Имя клиента\n#PHONE# - Телефон\n#EMAIL_TO# - Email получателя"
));
}
// Проверяем существование шаблона
$eventMessageResult = $eventMessage->GetList(
array(),
array("TYPE_ID" => "CONSULTATION_REQUEST")
);
if (!$eventMessageResult->Fetch()) {
// Создаем шаблон почтового события
$eventMessage->Add(array(
"ACTIVE" => "Y",
"EVENT_NAME" => "CONSULTATION_REQUEST",
"LID" => SITE_ID,
"EMAIL_FROM" => "#DEFAULT_EMAIL_FROM#",
"EMAIL_TO" => "#EMAIL_TO#",
"SUBJECT" => "Новая заявка на консультацию",
"BODY_TYPE" => "html",
"MESSAGE" => '<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
</head>
<body>
<p>Поступила новая заявка на консультацию!</p>
<p><b>Имя клиента:</b> #NAME#</p>
<p><b>Телефон:</b> #PHONE#</p>
<br/>
<p>Сообщение сгенерировано автоматически.</p>
</body>
</html>'
));
}
// === Настройка почтового события для новых заказов ===
$eventTypeResult = $eventType->GetList(array("TYPE_ID" => "SALE_NEW_ORDER_CUSTOM"));
if (!$eventTypeResult->Fetch()) {
// Создаем тип почтового события
$eventType->Add(array(
"EVENT_NAME" => "SALE_NEW_ORDER_CUSTOM",
"NAME" => "Новый заказ",
"LID" => "ru",
"DESCRIPTION" => "#ORDER_ID# - Номер заказа\n#ORDER_DATE# - Дата заказа\n#USER_NAME# - Имя покупателя\n#USER_PHONE# - Телефон\n#USER_EMAIL# - Email\n#PRICE# - Сумма заказа\n#CURRENCY# - Валюта\n#EMAIL# - Email получателя"
));
}
// Проверяем существование шаблона
$eventMessageResult = $eventMessage->GetList(
array(),
array("TYPE_ID" => "SALE_NEW_ORDER_CUSTOM")
);
if (!$eventMessageResult->Fetch()) {
// Создаем шаблон почтового события
$eventMessage->Add(array(
"ACTIVE" => "Y",
"EVENT_NAME" => "SALE_NEW_ORDER_CUSTOM",
"LID" => SITE_ID,
"EMAIL_FROM" => "#DEFAULT_EMAIL_FROM#",
"EMAIL_TO" => "#EMAIL#",
"SUBJECT" => "Новый заказ #ORDER_ID#",
"BODY_TYPE" => "html",
"MESSAGE" => '<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
</head>
<body>
<h2>Поступил новый заказ!</h2>
<p><b>Номер заказа:</b> #ORDER_ID#</p>
<p><b>Дата заказа:</b> #ORDER_DATE#</p>
<p><b>Имя покупателя:</b> #USER_NAME#</p>
<p><b>Телефон:</b> #USER_PHONE#</p>
<p><b>Email:</b> #USER_EMAIL#</p>
<p><b>Сумма заказа:</b> #PRICE# #CURRENCY#</p>
<br/>
<p>Перейти к заказу в административной панели</p>
<p>Сообщение сгенерировано автоматически.</p>
</body>
</html>'
));
}
// === Обработка формы консультации из футера ===
if (
$_SERVER['REQUEST_METHOD'] === 'POST' &&
isset($_POST['consultation_form']) &&
!empty($_POST['name']) &&
!empty($_POST['phone'])
) {
CEvent::Send(
"CONSULTATION_REQUEST",
SITE_ID,
array(
"NAME" => htmlspecialchars($_POST['name']),
"PHONE" => htmlspecialchars($_POST['phone']),
"EMAIL_TO" => COption::GetOptionString("main", "email_from")
)
);
// Можно добавить редирект или JSON-ответ, если это ajax
if (!empty($_SERVER['HTTP_X_REQUESTED_WITH']) && strtolower($_SERVER['HTTP_X_REQUESTED_WITH']) == 'xmlhttprequest') {
header('Content-Type: application/json');
echo json_encode(["success" => true]);
exit;
} else {
// Обычный редирект после отправки
header('Location: ' . $_SERVER['HTTP_REFERER']);
exit;
}
}
Loading…
Cancel
Save