memo-gen/index.html
2026-06-19 06:26:59 +00:00

260 lines
14 KiB
HTML
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<!DOCTYPE html>
<html lang="ru">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width,initial-scale=1">
<title>Служебная записка — генератор</title>
<style>
*{box-sizing:border-box;margin:0;padding:0}
body{font:16px/1.5 "Times New Roman",Georgia,serif;background:#f5f5f0;color:#1a1a1a;padding:40px 24px}
.container{max-width:900px;margin:0 auto}
h1{font-size:26px;font-weight:400;letter-spacing:1px;text-transform:uppercase;text-align:center;margin-bottom:4px;color:#222}
.sub{text-align:center;color:#666;font-size:14px;margin-bottom:40px;font-family:-apple-system,sans-serif}
.layout{display:grid;grid-template-columns:1fr 1fr;gap:32px;align-items:start}
.panel{background:#fff;border:1px solid #ddd;padding:28px;border-radius:2px;box-shadow:0 1px 4px rgba(0,0,0,.04)}
.panel h2{font-size:16px;font-weight:600;margin-bottom:16px;color:#333;font-family:-apple-system,sans-serif}
label{display:block;font-size:12px;font-weight:600;color:#555;margin-bottom:4px;text-transform:uppercase;letter-spacing:.5px;font-family:-apple-system,sans-serif}
input,textarea{width:100%;padding:10px 12px;border:1px solid #ccc;border-radius:2px;font:inherit;outline:none;transition:.15s}
input:focus,textarea:focus{border-color:#333}
textarea{resize:vertical;min-height:160px}
.form-row{display:grid;grid-template-columns:1fr 1fr;gap:12px;margin-bottom:12px}
button{width:100%;padding:12px;background:#1a1a1a;color:#fff;border:none;font:14px/1.4 -apple-system,sans-serif;font-weight:600;text-transform:uppercase;letter-spacing:1px;cursor:pointer;margin-top:16px;transition:.15s}
button:hover{background:#333}
.result-panel{background:#fff;border:1px solid #ddd;padding:28px;border-radius:2px;box-shadow:0 1px 4px rgba(0,0,0,.04);display:none}
.result-panel.show{display:block}
.doc-header{text-align:center;margin-bottom:28px;padding-bottom:20px;border-bottom:2px solid #1a1a1a}
.doc-header .org{font-size:14px;text-transform:uppercase;letter-spacing:1px;color:#555;margin-bottom:8px}
.doc-header .title{font-size:20px;font-weight:700;letter-spacing:2px;text-transform:uppercase}
.doc-meta{margin-bottom:24px}
.doc-meta .row{display:flex;margin-bottom:6px}
.doc-meta .row .lbl{width:100px;font-weight:600;color:#555;font-size:13px;text-transform:uppercase}
.doc-meta .row .val{flex:1;border-bottom:1px solid #ddd;padding-bottom:2px;font-size:15px}
.doc-body{font-size:15px;text-indent:30px;margin-bottom:24px;white-space:pre-wrap}
.doc-body i{font-style:italic;color:#555}
.doc-signature{margin-top:32px;padding-top:16px;border-top:1px solid #ddd}
.doc-signature .row{display:flex;justify-content:space-between;font-size:14px;color:#555}
.copy-btn{display:inline-block;margin-top:16px;padding:8px 20px;background:transparent;border:1px solid #999;color:#333;font:12px/1.4 -apple-system,sans-serif;text-transform:uppercase;letter-spacing:1px;cursor:pointer;transition:.15s}
.copy-btn:hover{background:#eee}
.rules-hint{font-size:12px;color:#888;margin-top:8px;line-height:1.4;font-family:-apple-system,sans-serif}
.rules-hint code{background:#f5f5f0;padding:1px 6px;border-radius:2px}
@media(max-width:720px){.layout{grid-template-columns:1fr;gap:24px}body{padding:24px 16px}.form-row{grid-template-columns:1fr}}
</style>
</head>
<body>
<div class="container">
<h1>Служебная записка</h1>
<p class="sub">Перевод текста в официальный стиль</p>
<div class="layout">
<div class="panel">
<h2>📝 Исходный текст</h2>
<div class="form-row">
<div><label>Кому</label><input id="to" placeholder="ФИО / должность"></div>
<div><label>От кого</label><input id="from" placeholder="ФИО / должность"></div>
</div>
<div class="form-row">
<div><label>Тема</label><input id="subject" placeholder="О чём записка"></div>
<div><label>Дата</label><input id="date" placeholder="дд.мм.гггг"></div>
</div>
<label>Текст детским / простым языком</label>
<textarea id="inputText" placeholder="Например: Витя из 5А разрисовал парту фломастером. Теперь парта вся в сердечках и надписях. Завуч сказала написать объяснительную."></textarea>
<div class="rules-hint">
<strong>Алгоритм перевода:</strong> исправляет орфографию → заменяет разговорные фразы на официальные → выстраивает в структуру служебной записки
</div>
<button onclick="generate()">Сформировать записку</button>
</div>
<div>
<div class="result-panel" id="result">
<div class="doc-header">
<div class="org">СЛУЖЕБНАЯ ЗАПИСКА</div>
<div class="title" id="docSubject"></div>
</div>
<div class="doc-meta">
<div class="row"><span class="lbl">Кому:</span><span class="val" id="docTo"></span></div>
<div class="row"><span class="lbl">От кого:</span><span class="val" id="docFrom"></span></div>
<div class="row"><span class="lbl">Дата:</span><span class="val" id="docDate"></span></div>
</div>
<div class="doc-body" id="docBody"></div>
<div class="doc-signature">
<div class="row">
<span>___________________</span>
<span id="docName"></span>
</div>
</div>
<button class="copy-btn" onclick="copyResult()">📋 Копировать</button>
</div>
</div>
</div>
</div>
<script>
const replacements = [
// Приветствия и обращения
[/привет|здорово|салют|хай/gi, 'Здравствуйте'],
[/ребята|пацаны|народ/gi, 'уважаемые коллеги'],
[/училка|препод|классуха/gi, 'педагогический работник'],
[/завуч/gi, 'заместитель директора по учебно-воспитательной работе'],
// Действия (разговорные → официальные)
[/(?:на)рисовал|разрисовал|исписал|разукрасил/gi, 'совершил действие по нанесению графических изображений'],
[/написал|накалякал|начеркал/gi, 'произвёл запись'],
[/сломал|поломал|разбил|испортил/gi, 'допустил повреждение'],
[/покрасил/gi, 'произвёл окрашивание'],
[/потерял|забыл|потерял/gi, 'утратил'],
[/ударил|толкнул|стукнул/gi, 'применил физическое воздействие'],
[/обзывал|обозвал/gi, 'допустил некорректные высказывания в адрес'],
[/подрались|побили/gi, 'вступили в конфликт с применением физической силы'],
[/списал|сдул/gi, 'допустил нарушение академической честности'],
[/опоздал/gi, 'допустил нарушение трудовой дисциплины в виде несвоевременного прибытия'],
[/прогулял/gi, 'не явился без уважительной причины'],
[/не сделал|не выполнил/gi, 'не исполнил возложенные обязанности'],
// Описания
[/парта|стол/gi, 'объект мебели'],
[/класс|кабинет/gi, 'учебное помещение'],
[/школа/gi, 'образовательное учреждение'],
[/урок/gi, 'учебное занятие'],
[/перемена|переменка/gi, 'перерыв между учебными занятиями'],
[/учиться/gi, 'осуществлять образовательную деятельность'],
[/двойка/gi, 'неудовлетворительная оценка'],
[/пятёрка/gi, 'отличная оценка'],
[/домашка/gi, 'домашнее задание'],
[/контрольная/gi, 'контрольное мероприятие'],
[/тетрадь/gi, 'рабочая тетрадь'],
[/дневник/gi, 'дневник успеваемости'],
[/фломастер|маркер|ручка/gi, 'канцелярская принадлежность'],
[/сердечки|сердечко/gi, 'изображения символического характера'],
[/надпись|надписи/gi, 'текстовые изображения'],
// Дети и люди
[/мальчик|мальчишка/gi, 'учащийся мужского пола'],
[/девочка|девчонка/gi, 'учащаяся женского пола'],
[/ученик/gi, 'обучающийся'],
[/ученица/gi, 'обучающаяся'],
[/директор|дир/gi, 'руководитель учреждения'],
// Связки
[/потому что|потому-то|так как/gi, 'в связи с тем что'],
[/поэтому/gi, 'в связи с вышеизложенным'],
[/вдруг|внезапно/gi, 'непредвиденно'],
[/наверное|наверно/gi, 'предположительно'],
[/очень/gi, 'в значительной степени'],
[/потом|после этого/gi, 'впоследствии'],
[/сейчас|щас/gi, 'в настоящее время'],
[/вчера/gi, 'в предшествующий день'],
[/сегодня/gi, 'в текущий день'],
[/завтра/gi, 'в следующий день'],
// Начало предложения
[/^ну |^ну,|^а |^а,|^и |^и,/gmi, ''],
[/^вот |^вот,/gmi, ''],
];
const phrases = {
intro: [
'Довожу до Вашего сведения, что',
'Сообщаю, что',
'Информирую о том, что',
'Ставлю Вас в известность о том, что',
'Настоящим докладываю, что',
'Докладываю следующее:',
],
conclusion: [
'На основании вышеизложенного прошу принять соответствующие меры.',
'Учитывая изложенное, прошу дать указания по данному вопросу.',
'Прошу рассмотреть данную ситуацию и принять решение.',
'В связи с вышеизложенным прошу Вашего распоряжения.',
'Прошу довести данную информацию до сведения ответственных лиц.',
],
request: [
'Прошу провести беседу с',
'Прошу принять меры в отношении',
'Прошу разобраться в сложившейся ситуации',
'Прошу дать указание',
],
};
function capitalize(s){
return s.charAt(0).toUpperCase()+s.slice(1);
}
function applyReplacements(text){
let t=text;
replacements.forEach(([re,val])=>{
// Simple approach: apply replacement, handling case
t=t.replace(re,val);
});
return t;
}
function generate(){
const to=document.getElementById('to').value.trim()||'Руководителю';
const from=document.getElementById('from').value.trim()||'Сотрудник';
const subject=document.getElementById('subject').value.trim()||'Служебная записка';
const date=document.getElementById('date').value.trim()||new Date().toLocaleDateString('ru-RU');
const text=document.getElementById('inputText').value.trim();
if(!text){
alert('Введите текст для перевода');
return;
}
// Apply replacements
let official=applyReplacements(text);
// Build body
const intro=phrases.intro[Math.floor(Math.random()*phrases.intro.length)];
const conclusion=phrases.conclusion[Math.floor(Math.random()*phrases.conclusion.length)];
const request=phrases.request[Math.floor(Math.random()*phrases.request.length)];
// Identify subject (first noun/person mentioned)
const firstPerson=official.match(/(учащийся[^,.]*|обучающийся[^,.]*|сотрудник[^,.]*|педагогический[^,.]*)/gi);
const personRef=firstPerson?firstPerson[0].toLowerCase():'указанным лицом';
let body=`${intro} ${capitalize(official)}
${request} ${personRef}. ${conclusion}`;
// Clean up
body=body.replace(/\s+/g,' ').replace(/ ,/g,',').replace(/ \./g,'.').replace(/\.\./g,'.');
body=body.replace(/ ,/g,',');
// Show result
document.getElementById('docSubject').textContent=subject.toUpperCase();
document.getElementById('docTo').textContent=to;
document.getElementById('docFrom').textContent=from;
document.getElementById('docDate').textContent=date;
document.getElementById('docBody').textContent=body;
document.getElementById('docName').textContent=from;
document.getElementById('result').classList.add('show');
}
function copyResult(){
const to=document.getElementById('docTo').textContent;
const from=document.getElementById('docFrom').textContent;
const date=document.getElementById('docDate').textContent;
const subject=document.getElementById('docSubject').textContent;
const body=document.getElementById('docBody').textContent;
const full=`СЛУЖЕБНАЯ ЗАПИСКА\n${subject}\n\nКому: ${to}\nОт кого: ${from}\nДата: ${date}\n\n${body}\n\n___________________\n${from}`;
navigator.clipboard.writeText(full).then(()=>{
const btn=document.querySelector('.copy-btn');
btn.textContent='✅ Скопировано';
setTimeout(()=>btn.textContent='📋 Копировать',2000);
}).catch(()=>{});
}
document.getElementById('inputText').addEventListener('keydown',e=>{if((e.ctrlKey||e.metaKey)&&e.key==='Enter')generate()});
</script>
</body>
</html>