Доброго времени суток начинающие программисты, в этом уроке мы будем создавать онлайн калькулятор услуг. В качестве примера мы будем брать калькулятор ремонта, который делает онлайн расчет стоимости ремонта.
Фишка этого калькулятора в том, что в итоге все расчеты можно сохранить в word документ и формирует он все данные за считанные мили-секунды.
Для чего мы создаем такой калькулятор расчетов услуг
- Быстрая готовая смета
- Сформированный документ можно уже отправлять клиенту
- Экономия времени пользователю, тем самым повышаем КПД
Какие методы используем
- Формирование шаблона на HTML
- Использование многомерного массива в input
- Запросы к базе данных для вывода услуг
- Расчет при помощи javascript
- Php формирование документа
Создаем калькулятор расчета за 6 простых шагов
Шаг 1. Создаем базу данных в mysql
В источниках есть дамп базы данных, в ней находится 2 таблицы. В последующих шагах мы будем к ним обращаться.
price_cat
- таблица с категориями
price_item
- таблица с услугами
Создаем базу данных импортируем файл calculator.sql в созданную базу данных и подключаемся к ней.
$dblocation = "localhost";
$dbname = "calculator";
$dbuser = "root";
$dbpasswd = "";
$dbcnx = @mysql_connect($dblocation,$dbuser,$dbpasswd);
if (!$dbcnx) {
echo( mysql_error() );
exit();
}
mysql_query("SET NAMES utf8",$dbcnx);
if (!@mysql_select_db($dbname, $dbcnx)) {
echo( mysql_error() );
exit();
}
Все готово. Теперь необходимо разметить html шаблон и одновременно формировать запросы к базе.
Шаг 2. Разметим html + php шаблон
Подключаем библиотеки, которые нам понадобятся
<link href="css/bootstrap.css" rel="stylesheet">
<link rel="stylesheet" href="//maxcdn.bootstrapcdn.com/font-awesome/4.3.0/css/font-awesome.min.css">
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.0/jquery.min.js"></script>
<script src="js/calculator.js"></script>
<script src="js/bootstrap.min.js"></script>
Обратите внимания:
Я использовал bootstrap компоненты, а так же библиотеку awesome иконки, а в calculator.js мы будем писать скрипт расчетов.
Разметка калькулятора
<div class="container">
<form method='post' action='save_word.php' >
<h1>Калькулятор ремонта</h1>
<?php
$res_category = mysql_query("SELECT *FROM price_cat ORDER BY sort");
if(mysql_num_rows($res_category)>0)
{
?>
<div class="panel-group" id="accordion">
<?
$category = mysql_fetch_array($res_category);
$i=1;
do
{
?>
<div class="panel panel-default category">
<div class="panel-heading">
<h4 class="panel-title">
<a data-toggle="collapse" class="open_category" aria-expanded="false" data-parent="#accordion" href="#price_cat<?php echo $i;?>">
<i class="fa fa-angle-down"></i> <?php echo $category["name"];?> <span class="summa_category"></span>
</a>
<input type="hidden" name="category[<?=$i;?>][name]" value="<?php echo $category["name"];?>" />
<input type="hidden" name="category[<?=$i;?>][summa]" value="" class="summa_category_input" />
</h4>
</div>
<div id="price_cat<?php echo $i;?>" class="panel-collapse collapse">
<div class="">
<?php
$res_item = mysql_query("SELECT *FROM price_item WHERE catid = '$category[id]'");
if(mysql_num_rows($res_item)>0)
{
?>
<div class="teble-responsive">
<table class="table table-striped">
<th>Наименование работ</th>
<th style="text-align:center;">Ед. изм.</th>
<th style="text-align:center;">Стоимость</th>
<th style="text-align:center;">Кол-во</th>
<th style="text-align:center;">Сумма</th>
<?
$item = mysql_fetch_array($res_item);
$k=1;
do
{
$price = number_format($item["cost"], 0, '', ' ');
?>
<tr>
<td>
<span class=""><?php echo $item["name"];?></span>
<input type="hidden" name="category[<?=$i;?>][items][<?=$k;?>][name]" value="<?php echo $item["name"];?>" />
</td>
<td style="text-align:center;">
<span class=""><?php echo $item["shortdesc"];?></span>
<input type="hidden" name="category[<?=$i;?>][items][<?=$k;?>][ed_izm]" value="<?php echo $item["shortdesc"];?>" />
</td>
<td style="text-align:center;">
<span class=""><?php echo $price;?></span>
<input type="hidden" name="category[<?=$i;?>][items][<?=$k;?>][price]" value="<?php echo $item["cost"];?>" />
</td>
<td><input type="number" step="0.1" min="0" class="form-control calc" name="category[<?=$i;?>][items][<?=$k;?>][kolvo]" value="" style="width:70px; margin:0 auto;"></td>
<td><input type="text" readonly="readonly" class="form-control item_summa" name="category[<?=$i;?>][items][<?=$k;?>][summa]" value="" style="width:80px; margin:0 auto; text-align:center;"></td>
</tr>
<?
$k++;
}
while($item = mysql_fetch_array($res_item));
?>
</table>
</div>
<?
}
?>
</div>
</div>
<div class="panel-body" style="border-top:1px solid #ddd;">
<div class="pull-right">
<div><strong>Итого:</strong> <big class="summa_category">0</big> руб.</div>
</div>
</div>
</div>
<?
$i++;
}
while($category = mysql_fetch_array($res_category));
?>
</div>
<?
}
?>
<div class="panel-body well well-sm">
<div class="row">
<div class="col-xs-12 col-md-6 "><button class="btn btn-primary btn-sm" name="save_word">Сохранить в WORD документ</button></div>
<div class="col-xs-12 col-md-6">
<div class=" pull-right" style="font-size:20px;">
<strong>Итого:</strong> <span class="total">0</span> руб.
<input type="hidden" name="total" class="total_input" value="" />
</div>
</div>
</div>
</div>
</form>
</div>
Как видим ничего сложного нет, очень простые запросы к базе, очень простой html код. Единственное на что хотел обратить внимание, это на то что мы используем многомерный массив input. В файле обработчике мы будет работать с ними и научимся извлекать нужные данные из них.
Теперь самое интересное. Напишем скрипт для расчета стоимости услуг на javascript.
Шаг 3. Пишем скрипт на javascript онлайн расчета
Некоторые строки я пояснил прямо в коде.
$(function(){
// смена стрелочки у категории
$(".open_category").click(function(){
var status = $(this).attr("aria-expanded")
if(status=="false")
{
$(this).find("i").attr("class","fa fa-angle-up");
}
else
{
$(this).find("i").attr("class","fa fa-angle-down");
}
})
// событие при наборе кол-ва в калькуляторе
$(".calc").on("change keyup", function(){
var value = $(this).val();
var price = $(this).parent().prev().find("input").val();
price = price.replace(/\s/g, ''); // удаляем пробелы
var item_summa = value*price;
item_summa = item_summa.Crop(2); // 2 знаka после запятой
$(this).parent().next().find("input").val(item_summa);
var summa_category = 0; // сюда будем загонять сумму в каждоый категории
var total_summa = 0; // сюда будем загонять итоговую сумму
var item_summa_category = $(this).parent().next().find("input");
$(item_summa_category).each(function(){ // пробегаемся по всем суммам и суммируем
var k = parseFloat($(this).val());
if(!k || k==0){k=0;}
summa_category += k;
})
// записываем расчеты по категориям
$(this).parents(".category").find(".summa_category").text(summa_category);
$(this).parents(".category").find(".summa_category_input").val(summa_category);
$("big.summa_category").each(function(){ // пробегаемся по всем суммам в категориях и суммируем
var t = parseFloat($(this).text());
if(!t || t==0){t=0;}
total_summa += t; // считаем общую стоимость
})
// выводим итоговую сумму
$(".total").text(total_summa);
$(".total_input").val(total_summa);
})
})
// функция знаки после запятой
Number.prototype.Crop = function (x){
var s = this+'', a = s.split('.');
a[1]=a[1]||'';
return parseFloat(a[0]+'.'+a[1].substring(0,x));
}
Отлично теперь, если вы сделали все правильно, то у наш созданный калькулятор уже должен считать.
Шаг 4. Пишем скрипт формирования содержимого в word.docx документ.
В исходниках есть файл sample.rtf, его вы должны разместить у Вас на сервере. Он послужит нам шаблоном для создания документа формата .docx на php. Он так же содержит метки, куда мы будем присваивать переменные, созданные в файле save_word.php. Этот файл и есть обработчик формирования word документа.
Файл save_word.php
header('Content-Type: text/html; charset= utf-8');
$categories = isset($_POST['category']) ? $_POST['category'] : array(); // Записываем в многомерный массив все инпуты, которые мы разметели с помощью цикла в php
//В Переменную word мы будем присваивать все что мы расчитали.
$word = "<div style=\"font-family: Helvetica, Arial, sans-serif;\"><table cellpadding=\"0\" border=\"1\" cellspacing=\"0\" style=\"width:100%; border-color: #ddd;\">";
// пробегаемся по категориям
foreach($categories as $category) {
if($category["summa"]!=0) //Проверяем, если есть расчеты в категории, то считаем.
{
// Обратите внимания, в переменнюу word мы присваем с точкой в начале ".=", это значит что мы добавляем содержимое к тому что было ранее. То есть иными словами Лево+Право=ЛевоПраво
$word .= "<tr><th colspan=\"5\"><div style=\"font-family: Helvetica, Arial, sans-serif; padding:15px; text-align:left; background: #ececec; font-size: 16px;\">$category[name] ($category[summa] руб.)</th></div></tr>";
$word .= "
<tr style=\"font-size:13px;\">
<td><div style=\"padding:5px; font-family: Helvetica, Arial, sans-serif;\"><strong>Наименование работ</strong></div></td>
<td><div style=\"font-family: Helvetica, Arial, sans-serif; padding:5px; text-align:center\"><strong>Ед. изм.</strong></div></td>
<td><div style=\"font-family: Helvetica, Arial, sans-serif;padding:5px; text-align:center\"><strong>Стоимость</strong></div></td>
<td><div style=\"font-family: Helvetica, Arial, sans-serif;padding:5px; text-align:center\"><strong>Кол-во</strong></div></td>
<td><div style=\"font-family: Helvetica, Arial, sans-serif;padding:5px; text-align:center\"><strong>Сумма</strong></div></td>
</tr>
";
foreach($category["items"] as $items) //Пробегаемся по всем услугам
{
if($items["summa"]!=0) // По аналогии. ну тут понятно думаю.
{
$word .="<tr style=\"font-size:12px;\">
<td><div style=\"font-family: Helvetica, Arial, sans-serif;padding:5px;\">$items[name]</div></td>
<td><div style=\"font-family: Helvetica, Arial, sans-serif;padding:5px; text-align:center;\">$items[ed_izm]</div></td>
<td><div style=\"font-family: Helvetica, Arial, sans-serif;padding:5px; text-align:center;\">$items[price]</div></td>
<td><div style=\"font-family: Helvetica, Arial, sans-serif;padding:5px; text-align:center;\">$items[kolvo]</div></td>
<td><div style=\"font-family: Helvetica, Arial, sans-serif;padding:5px; text-align:center;\">$items[summa]</div></td>
</tr>";
}
}
}
}
$word .="</table>";
$word .="<div style=\"padding:15px; margin-top:30px; font-size:18px; \"><strong>Итого:</strong> ".$_POST['total']." руб.</div></div>";
$d=Date('d.m.Y');
$name_doc = "Ваш прайс-лист ($d)";
//Сгенерировать заголовки, которые упростят браузеру выбор требуемого приложения для визуализации
header('Content-type: application/msword');
header('Content-disposition: inline; filename='.$name_doc.'.doc');
// Открыть файл шаблона
$filename = 'sample.rtf';
$fp = fopen($filename,'r');
//прочитать шаблон в перменную
$output = fread($fp, filesize($filename));
fclose($fp);
//Заменить заполнители в шаблоне требуемыми переменными
$output = str_replace('<<NAME>>',$word,$output);
//Отправить сгенерированный документ в браузер
html_entity_decode(iconv("utf-8", "windows-1251", $output), ENT_QUOTES, "windows-1251");
echo $output
В некоторых моментах мне было лень присваивать классы, прописывать к ним стили, а потом подключать новую CSS. По этому я писал стили прямо в коде в тегах, конечно же плохой пример, не делайте так, но из-за 2-3 строк, тоже время терять не хочется.
Все готово, можете тестировать и визуализировать выводимый word формат.
Вывод
В этом уроке мы создали онлайн калькулятор расчета услуг, на примере калькулятора ремонта, позаимствовав идею у сайта remont-cityper.ru. Написанный нами код очень сильно отличается от кода, который использован в демо примере. ( можете убедится сами). Так же мы научились создавать word документ под средством php, использовав шаблон rtf и специальные метки. Это отличный урок по созданию счетов, бланков, прайс-листов и т.д.
Пишите комментарии по этому поводу, я буду раз услышать от вас рекомендации или советы.