add: core (01) драфт... работает!! Генерация SVG проходит!!!

This commit is contained in:
2026-08-23 22:14:49 +03:00
parent f015351c42
commit 05bb583d8a
7 changed files with 425 additions and 13 deletions
+13 -1
View File
@@ -110,9 +110,21 @@ val=>{if(val)document.documentElement.classList.add('dark');else document.docume
{% endblock EXTRA_LD_JSON %}</script>
<script src="{% static 'js/alpine.min.js' %}" defer></script>
<script src="{% static 'js/htmx.min.js' %}" defer></script>
<script>
document.addEventListener('htmx:configRequest', function(evt) {
var token = '{{ csrf_token }}';
if (!token) {
var match = document.cookie.match(/csrftoken=([^;]+)/);
if (match) token = match[1];
}
if (token) {
evt.detail.headers['X-CSRFToken'] = token;
}
});
</script>
{% block EXTRA_HEAD %}{% endblock EXTRA_HEAD %}
</head>
<body class="bg-stone-50 text-emerald-700 dark:bg-zinc-950 dark:text-emerald-100 font-mono">{% block ADD_CSS1 %}{% endblock %}{% block ADD_CSS2 %}{% endblock %}{% block ADD_CSS3 %}{% endblock %}{% block BODY %}
<body hx-headers='{"X-CSRFToken": "{{ csrf_token }}"}' class="bg-stone-50 text-emerald-700 dark:bg-zinc-950 dark:text-emerald-100 font-mono">{% block ADD_CSS1 %}{% endblock %}{% block ADD_CSS2 %}{% endblock %}{% block ADD_CSS3 %}{% endblock %}{% block BODY %}
{% include "block/header.html" %}
<main id="main-content" class="mx-auto min-h-screen max-w-7xl px-4 py-8">
{% block CONTENT %}{% endblock CONTENT %}
+26
View File
@@ -0,0 +1,26 @@
{% if error %}
<div class="text-rose-500 flex flex-col items-center gap-4 text-center px-6">
<svg class="w-16 h-16 text-rose-500 opacity-80 animate-pulse" fill="none" viewBox="0 0 24 24" stroke="currentColor">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="1.5" d="M12 9v2m0 4h.01m-6.938 4h13.856c1.54 0 2.502-1.667 1.732-3L13.732 4c-.77-1.333-2.694-1.333-3.464 0L3.34 16c-.77 1.333.192 3 1.732 3z"/>
</svg>
<p class="font-mono text-sm font-bold uppercase tracking-wider text-rose-600 dark:text-rose-400">
{{ error }}
</p>
</div>
{% else %}
<div class="w-full h-full flex items-center justify-center p-4 select-none overflow-hidden" id="svg-canvas-container">
{{ svg_content|safe }}
</div>
<!-- Плавающие кнопки действий -->
<div class="absolute bottom-6 right-6 flex items-center gap-3 translate-y-20 group-hover:translate-y-0 transition-transform duration-300 pointer-events-none">
<button id="like-to-gallery" type="button" title="Нравится!"
class="pointer-events-auto flex items-center gap-2 bg-emerald-600/90 hover:bg-emerald-600 text-white text-xs font-bold uppercase tracking-wide backdrop-blur-md px-4 py-2.5 rounded-full shadow-xl transition-all hover:scale-105 active:scale-95 cursor-pointer">
<span>Кандидат в галерею транса</span>
<svg class="w-5 h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2"
d="M4.318 6.318a4.5 4.5 0 000 6.364L12 20.364l7.682-7.682a4.5 4.5 0 00-6.364-6.364L12 7.636l-1.318-1.318a4.5 4.5 0 00-6.364 0z"/>
</svg>
</button>
</div>
{% endif %}
+34 -3
View File
@@ -23,6 +23,7 @@
hasChanges: true, /* Флаг наличия правок в форме для активности кнопки */
hasImage: false, /* Флаг загрузки пользовательского файла */
timer: null, /* Ссылка на таймер удержания анимации размышления */
copied: false, /* Флаг успешного копирования в буфер */
/* Метод запуска состояния размышления (8 секунд) */
startThinking() {
@@ -32,6 +33,29 @@
this.isLoading = false;
this.hasChanges = false;
}, 8000);
},
copySvg() {
const svg = document.querySelector('#preview svg');
if (!svg) return;
navigator.clipboard.writeText(svg.outerHTML).then(() => {
this.copied = true;
setTimeout(() => this.copied = false, 2000);
});
},
downloadSvg() {
const svg = document.querySelector('#preview svg');
if (!svg) return;
const blob = new Blob([svg.outerHTML], {type: 'image/svg+xml;charset=utf-8'});
const url = URL.createObjectURL(blob);
const a = document.createElement('a');
a.href = url;
a.download = 'hypn0-art.svg';
document.body.appendChild(a);
a.click();
document.body.removeChild(a);
URL.revokeObjectURL(url);
}
}">
@@ -45,7 +69,9 @@
@change="hasChanges = true"
@input="hasChanges = true"
@htmx:before-request="startThinking()"
@htmx:after-request="isLoading = false; hasChanges = false"
class="relative bg-white dark:bg-zinc-900 p-6 rounded-2xl shadow-sm border border-stone-200 dark:border-zinc-800 overflow-hidden">
{% csrf_token %}
<!-- Фоновая спираль размышления при генерации (прижата снизу на всю левую панель) -->
<div x-show="isLoading"
@@ -65,6 +91,7 @@
<label class="block text-sm font-bold mb-2 uppercase tracking-wider text-stone-500 dark:text-zinc-400">Источник</label>
<div class="relative group">
<input type="file" name="image" accept="image/*"
@change="hasImage = $el.files.length > 0; hasChanges = true"
class="absolute inset-0 w-full h-full opacity-0 cursor-pointer z-10">
<div
class="border-2 border-dashed border-stone-300 dark:border-zinc-700 group-hover:border-emerald-500 rounded-xl p-8 flex flex-col items-center justify-center text-center transition-colors">
@@ -410,13 +437,17 @@
<div class="grid grid-cols-2 gap-4">
<button
class="bg-stone-800 text-white dark:bg-zinc-800 py-3.5 rounded-xl font-bold flex items-center justify-center gap-2 hover:bg-stone-700 transition-colors">
type="button"
@click="copySvg()"
class="bg-stone-800 text-white dark:bg-zinc-800 py-3.5 rounded-xl font-bold flex items-center justify-center gap-2 hover:bg-stone-700 transition-colors cursor-pointer active:scale-95">
<svg class="w-5 h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path d="M8 16H6a2 2 0 01-2-2V6a2 2 0 012-2h8a2 2 0 012 2v2m-6 12h8a2 2 0 002-2v-8a2 2 0 00-2-2h-8a2 2 0 00-2 2v8a2 2 0 002 2z"/></svg>
КОПИРОВАТЬ SVG
<span x-text="copied ? 'СКОПИРОВАНО В БУФЕР!' : 'КОПИРОВАТЬ SVG'"></span>
</button>
<button
class="bg-emerald-600 text-white py-3.5 rounded-xl font-bold flex items-center justify-center gap-2 hover:bg-emerald-500 transition-colors shadow-lg shadow-emerald-900/20">
type="button"
@click="downloadSvg()"
class="bg-emerald-600 text-white py-3.5 rounded-xl font-bold flex items-center justify-center gap-2 hover:bg-emerald-500 transition-colors shadow-lg shadow-emerald-900/20 cursor-pointer active:scale-95">
<svg class="w-5 h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path d="M4 16v1a2 2 0 002 2h12a2 2 0 002-2v-1m-4-4l-4 4m0 0l-4-4m4 4V4"/></svg>
СКАЧАТЬ
</button>