Browse Source

Печать работает корректно

Улучшения качества жизни
Вадим Королёв 1 year ago
parent
commit
419f24718c

+ 14 - 10
src/Controllers/AutoGostController.php

@@ -20,12 +20,19 @@ use Pockit\AutoGostSections\SubSection;
 
 class AutoGostController {
 
+	// Применение правил подписи рисунков
+	// https://www.php.net/manual/ru/function.ucfirst.php#84122
+	private static function makeValidPictureTitle(string $title) : string {
+		return mb_strtoupper(mb_substr($title, 0, 1)) .
+			mb_strtolower(mb_substr($title, 1));
+	}
+
 	// Загрузка изображений
 	public static function uploadImage() {
 
 		if (is_uploaded_file($_FILES['file']['tmp_name'])) {
 			$mime_type = mime_content_type($_FILES['file']['tmp_name']);
-			$filepath = tempnam(rootdir."/img/autogost", "rgnupload");
+			$filepath = index_dir."/wwwroot/img/autogost/rgnupload".uniqid();
 
 			if ($mime_type == "image/png") {
 				// Конвертирование png в gif
@@ -35,7 +42,7 @@ class AutoGostController {
 				imagegif($gif_image, $filepath);
 			} else {
 				// Просто перемещение файла
-				$filepath = tempnam(rootdir."/img/autogost", "rgnupload");
+				$filepath = tempnam(index_dir."/img/autogost", "rgnupload");
 				move_uploaded_file($_FILES['file']['tmp_name'], $filepath);
 			}
 
@@ -116,7 +123,7 @@ class AutoGostController {
 					$_POST['work_type'],
 					$_POST['number'],
 					$_POST['notice'],
-					"!-\n!\n#{$work_type['name_nom']} №{$_POST['number']}\n"
+					"@titlepage\n@section:{$work_type['name_nom']} №{$_POST['number']}\n@section:Ответы на контрольные вопросы"
 				);
 
 				// Перенаправляем на предпросмотр этого отчёта
@@ -197,10 +204,13 @@ class AutoGostController {
 					} else {
 						$imgwidth = "";
 					}
+
+					$pictitle = self::makeValidPictureTitle($command[2]);
+					
 					end($document)->addHTML(
 						"<figure>
 							<img ".$imgwidth." src='/img/autogost/".$command[1]."'>
-							<figcaption>Рисунок ".$current_img." - ".$command[2]."</figcaption>
+							<figcaption>Рисунок ".$current_img." - ".$pictitle."</figcaption>
 						</figure>"
 					);
 					$current_img++;
@@ -237,14 +247,8 @@ class AutoGostController {
 			$report
 		);
 
-		echo "<!DOCTYPE html>";
-		echo "<html>";
-		echo "<head><link rel='stylesheet' href='/css/autogost-report.css'></head>";
-		echo "<body><div id='preview'>";
 		foreach ($document as $section) {
 			$section->output();
 		}
-		echo "</div></body>";
-		echo "</html>";
 	}
 }

+ 4 - 3
src/Views/AutoGostEditView.php

@@ -18,17 +18,17 @@ class AutoGostEditView extends LayoutView {
 
 	public function content():void { ?>
 
-<div id='control-sidebar' class='card no-print'>
+<div id='control-sidebar' class='card'>
 	
 	<button class='btn selected' id='switchMarkup'>Разметка</button>
 	<button class='btn' id='switchPreview'>Превью</button>
 	<button class='btn' id="printReport">Печать</button>
-	<button class='btn'>Получить название файла</button>
+	<button class='btn' id="getFilename">Получить название файла</button>
 	<button class='btn success' id='saveMarkupButton'>Сохранить</button>
 	
 </div>
 
-<div style='margin-left:200px'>
+<div style='margin-left:215px'>
 	<div class='card' id="controls">
 		<textarea id="markuparea" autocomplete="off"><?= $this->markup ?></textarea>
 		<div style='display: none;' id="preview"></div>
@@ -36,6 +36,7 @@ class AutoGostEditView extends LayoutView {
 </div>
 
 <input type='hidden' id='idInput' value='<?= $this->report_id ?>'>
+<input type='hidden' id='filename' value='<?= $this->filename ?>'>
 
 <?php }
 }

+ 29 - 2
wwwroot/css/autogost-report.css

@@ -1,6 +1,6 @@
 #preview {
 	font-family: "Times New Roman";
-	background-color: #383838;
+	background-color: var(--gray-3);
 	color: #aaaaaa;
 	font-size: 12pt;
 	margin: 0;
@@ -121,4 +121,31 @@
 .page .dt {left:8.25cm;bottom:4mm;}
 .page .co {left:9.1cm;bottom:8mm;right:1.5cm;font-size:22px;text-align:center;}
 .page .pl {left:19.55cm;bottom:14mm;}
-.page .cp {left:19.5cm;bottom:7mm;right:0.5cm;text-align:center;}
+.page .cp {left:19.5cm;bottom:7mm;right:0.5cm;text-align:center;}
+
+/* Стили для печатания */
+@media print {
+	body {
+		visibility: hidden;
+	}
+
+	#preview {
+		visibility: visible;
+		position: absolute;
+		top: 0;
+		left: 0;
+	}
+
+	#preview .page {
+		margin: 0;
+		border-radius: 0;
+		color: #000;
+		background-color: #fff;
+		border: none;
+	}
+}
+
+@print {
+	size: A4;
+	margin: 0;
+}

+ 1 - 1
wwwroot/css/pockit.css

@@ -282,7 +282,7 @@ a:hover {
 #control-sidebar {
 	margin: 0;
 	padding: 1em;
-	width: 200px;
+	width: 215px;
 	position: fixed;
 	height: 100%;
 	overflow: auto;

+ 1 - 1
wwwroot/img/autogost/.gitignore

@@ -1 +1 @@
-*.tmp
+rgn*

BIN
wwwroot/img/autogost/smallframe.png


+ 107 - 43
wwwroot/js/autogostpreview.js

@@ -1,29 +1,40 @@
-// Текущее состояние страницы
-// 0 - режим редактирования
-// 1 - режим просмотра превью
-var current_state = 0;
-var markup_area = $('#markuparea');
-var preview_area = $('#preview');
-var saveButton = $('#saveMarkupButton');
+var markupArea = $('#markuparea');
+var previewArea = $('#preview');
+
+var btnPreview = $("#switchPreview");
+var btnMarkup = $("#switchMarkup");
+var btnPrint = $('#printReport');
+var btnSave = $('#saveMarkupButton');
+var btnFilename = $('#getFilename');
+
+var reportId = $("#idInput").val();
+var filename = $("#filename").val().replace(/[&\/\\#,+()$~%.'":*?<>{}]/g, "");
+
+var isDirty = false;
 
 $(document).ready(function() {
 	textAreaAdjust(document.getElementById("markuparea"));
 
-	$("#saveMarkupButton").click(function(e) {
+	markupArea.keyup(function() {
+		isDirty = true;
+	});
+
+	// Сохранение по кнопке
+	btnSave.click(function(e) {
 		saveMarkup();
 	});
 
 	// Сохранение на Ctrl+S
 	document.addEventListener("keydown", function(e) {
-	  if (e.keyCode === 83 && (navigator.platform.match("Mac") ? e.metaKey : e.ctrlKey)) {
-		e.preventDefault();
-		saveMarkup();
-	  }
+		if (e.keyCode === 83 && (navigator.platform.match("Mac") ? e.metaKey : e.ctrlKey)) {
+			e.preventDefault();
+			saveMarkup();
+		}
 	}, false);
 
 	// Вставка картинок на Ctrl+V
 	// https://stackoverflow.com/a/6338207
-	$("#markuparea").on('paste', function (e) {
+	markupArea.on('paste', function (e) {
 		let items = (e.clipboardData || e.originalEvent.clipboardData).items;
 		for (let index in items) {
 			let item = items[index];
@@ -44,8 +55,8 @@ $(document).ready(function() {
 						response = JSON.parse(response);
 
 						if (response.ok) {
-							const line = "?"+response.filename+":"+"Подпись изображения";
-							markup_area.val(markup_area.val() + line);
+							const line = "\n@img:"+response.filename+":Изображение";
+							insertAtCursor(document.getElementById("markuparea"), line);
 						}
 					}
 				});
@@ -53,52 +64,66 @@ $(document).ready(function() {
 		}
 	});
 	
-	$("#switchPreview").click(function() {
+	btnPreview.click(function() {
 		$("#switchMarkup").removeClass('selected');
 		$("#switchPreview").addClass('selected');
-		preview_area.html('<div class="loader"></div>');
-		markup_area.hide();
-		preview_area.show();
+		previewArea.html('<div class="loader"></div>');
+		markupArea.hide();
+		previewArea.show();
 		saveMarkup();
 		updatePreview();
 	});
 
-	$("#switchMarkup").click(function() {
+	btnMarkup.click(function() {
 		$("#switchMarkup").addClass('selected');
 		$("#switchPreview").removeClass('selected');
-		markup_area.show();
-		preview_area.hide();
+		textAreaAdjust(markupArea);
+		markupArea.show();
+		previewArea.hide();
 		saveMarkup();
 	});
 
-	$("#printReport").click(function() {
+	// Скопировать текст в буфер обмена
+	btnFilename.click(async function() {
+		await navigator.clipboard.writeText(filename);
+		btnFilename.text("Название скопировано");
+		btnFilename.blur();
+	});
+
+	btnFilename.mouseleave(function () {
+		btnFilename.text("Получить название файла");
+	});
+
+	btnPrint.click(function() {
 		saveMarkup();
 		updatePreview(true);
-	})
+	});
 });
 
-// При печати текста заставляет textbox расширяться
+// Заставляет textarea расширяться так, чтобы был текст в ней был полностью
+// виден
 function textAreaAdjust(element) {
-	element.style.height = "1px";
-	element.style.height = (25+element.scrollHeight)+"px";
+	if (element.scrollHeight > element.clientHeight) {
+		// Содержимое полностью не вмещается
+		element.style.height = "calc(1lh + " + element.scrollHeight +"px)";
+	}
 }
 
-function updatePreview(then_print=false) {
-	const str = document.location.toString();
-	const slash_idx = str.lastIndexOf('/');
-	const report_id = str.substring(slash_idx + 1);
-	$.post(
-		"/autogost/gethtml",
-		{
-			report_id: report_id
+// Обновляет #preview на странице, отсылая запрос на получение HTML
+function updatePreview(thenPrint=false) {
+	$.ajax({
+		url: "/autogost/gethtml",
+		type: "post",
+		data: {
+			report_id: reportId
 		},
-		function (data, textStatus, xhr) {
-			$("#preview").html(data);
-			if (then_print) {
+		success: function (data, textStatus, xhr) {
+			previewArea.html(data);
+			if (thenPrint) {
 				window.print();
 			}
 		}
-	);
+	});
 }
 
 // Сохраняет разметку для данного отчёта
@@ -107,11 +132,50 @@ function saveMarkup() {
 		url: "/reports/update",
 		type: "post",
 		data: {
-			id: $("#idInput").val(),
-			markup: $("#markuparea").val()
+			id: reportId,
+			markup: markupArea.val()
 		},
 		success: function() {
-			saveButton.blur();
+			isDirty = false;
+			btnSave.blur();
 		}
 	});
-}
+}
+
+// Вставка текста на текущую позицию курсора
+// https://stackoverflow.com/a/11077016
+function insertAtCursor(myField, myValue) {
+    //IE support
+    if (document.selection) {
+        myField.focus();
+        sel = document.selection.createRange();
+        sel.text = myValue;
+    }
+    //MOZILLA and others
+    else if (myField.selectionStart || myField.selectionStart == '0') {
+        var startPos = myField.selectionStart;
+        var endPos = myField.selectionEnd;
+        myField.value = myField.value.substring(0, startPos)
+            + myValue
+            + myField.value.substring(endPos, myField.value.length);
+    } else {
+        myField.value += myValue;
+    }
+    textAreaAdjust(myField);
+    isDirty = true;
+}
+
+// https://developer.mozilla.org/en-US/docs/Web/API/Window/beforeunload_event
+const beforeUnloadHandler = (event) => {
+	if (isDirty == false) {
+		return true;
+	}
+
+	// Recommended
+	event.preventDefault();
+
+	// Included for legacy support, e.g. Chrome/Edge < 119
+	event.returnValue = true;
+};
+
+window.addEventListener("beforeunload", beforeUnloadHandler);