diff --git a/app.db b/app.db index bfe436b..67f578d 100644 Binary files a/app.db and b/app.db differ diff --git a/app.py b/app.py index 0e2436f..ddd832b 100644 --- a/app.py +++ b/app.py @@ -332,6 +332,7 @@ def api_vk(): @app.route("/api/posts", methods=["POST", "GET"]) def api_posts(): + response = {"status": "ok"} match request.method: case "POST": requestData = request.json @@ -362,32 +363,34 @@ def api_posts(): logger.info("Обновление расписания публикации") try: scheduler = PostScheduler.query.first() - startTime = schedulerData.get("startTime", None) - endTime = schedulerData.get("endTime", None) - interval_minutes = schedulerData.get("interval_minutes", None) + hour = schedulerData.get("hour", None) + minute = schedulerData.get("minute", None) enabled = schedulerData.get("enabled", None) if scheduler: - if startTime: - scheduler.start_hour = int(startTime) - if endTime: - scheduler.end_hour = int(endTime) - if interval_minutes: - scheduler.interval_minutes = int(interval_minutes) + if hour is not None: + if scheduler.hour != hour: + scheduler.hour = hour + if minute is not None: + if scheduler.minute != minute: + scheduler.minute = minute if enabled is not None: - scheduler.enabled = enabled + if scheduler.enabled != enabled: + scheduler.enabled = enabled else: db.session.merge( PostScheduler( - start_hour=int(startTime), - end_hour=int(endTime), - interval_minutes=int(interval_minutes), + hour=int(hour), + minute=int(minute), enabled=enabled, ) ) db.session.commit() + enable_publish_job() + scheduleInfo = get_scheduler_status() + response["next_run_time"] = scheduleInfo.get("next_run_time") except Exception as e: logger.error(f"Ошибка при обновлении расписания публикации: {e}") - return jsonify({"status": "ok"}) + return jsonify(response) case "GET": queryParams = request.args.to_dict() diff --git a/db.py b/db.py index 66cf85e..298e137 100644 --- a/db.py +++ b/db.py @@ -123,9 +123,8 @@ class PostScheduler(db.Model): __tablename__ = "post_scheduler" id = db.Column(db.Integer, primary_key=True) - start_hour = db.Column(db.Integer) - end_hour = db.Column(db.Integer) - interval_minutes = db.Column(db.Integer) + hour = db.Column(db.Integer) + minute = db.Column(db.Integer) enabled = db.Column(db.Boolean) created_at = db.Column(db.DateTime, default=datetime.now) updated_at = db.Column(db.DateTime, default=datetime.now, onupdate=datetime.now) @@ -133,9 +132,8 @@ class PostScheduler(db.Model): def toDict(self): return { "id": self.id, - "start_hour": self.start_hour, - "end_hour": self.end_hour, - "interval_minutes": self.interval_minutes, + "hour": self.hour, + "minute": self.minute, "enabled": self.enabled, "created_at": self.created_at.strftime("%Y-%m-%d %H:%M:%S"), "updated_at": self.updated_at.strftime("%Y-%m-%d %H:%M:%S"), diff --git a/scheduler.py b/scheduler.py index 246c201..6b1c066 100644 --- a/scheduler.py +++ b/scheduler.py @@ -75,19 +75,11 @@ def enable_publish_job(): disable_publish_job() return - start_hour = scheduleData.start_hour - end_hour = scheduleData.end_hour - interval_minutes = scheduleData.interval_minutes - trigger = CronTrigger( - hour="12", - minute="0", + hour=f"{scheduleData.hour}", + minute=f"{scheduleData.minute}", day="*", ) - # trigger = CronTrigger( - # hour=f"{start_hour}-{end_hour - 1}", - # minute=f"*/{interval_minutes}", - # ) scheduler.add_job( vk_publish_job, diff --git a/static/css/posts.css b/static/css/posts.css index bfb3d38..e7520e6 100644 --- a/static/css/posts.css +++ b/static/css/posts.css @@ -17,7 +17,7 @@ /* Таблица сотрудников */ .table-responsive { - max-height: 800px; + max-height: 575px; overflow-y: auto; } diff --git a/static/js/posts.js b/static/js/posts.js index e1fb641..875f4eb 100644 --- a/static/js/posts.js +++ b/static/js/posts.js @@ -20,9 +20,8 @@ function saveOriginalSettings() { selected_users: getSelectedUsers(), static_text: document.getElementById('static_text').value, full_name: document.getElementById('full_name').checked, - start_hour: parseInt(document.getElementById('start_hour').value), - end_hour: parseInt(document.getElementById('end_hour').value), - interval_minutes: parseInt(document.getElementById('interval_minutes').value), + hour: parseInt(document.getElementById('hour').value), + minute: parseInt(document.getElementById('minute').value), enabled: document.getElementById('scheduler_enabled').checked }; } @@ -38,7 +37,7 @@ function setupChangeListeners() { }); // Поля формы - const formFields = ['static_text', 'start_hour', 'end_hour', 'interval_minutes']; + const formFields = ['static_text', 'hour', 'minute']; formFields.forEach(field => { const element = document.getElementById(field); if (element) { @@ -58,9 +57,8 @@ function checkForChanges() { selected_users: getSelectedUsers(), static_text: document.getElementById('static_text').value, full_name: document.getElementById('full_name').checked, - start_hour: parseInt(document.getElementById('start_hour').value), - end_hour: parseInt(document.getElementById('end_hour').value), - interval_minutes: parseInt(document.getElementById('interval_minutes').value), + hour: parseInt(document.getElementById('hour').value), + minute: parseInt(document.getElementById('minute').value), enabled: document.getElementById('scheduler_enabled').checked }; @@ -194,9 +192,8 @@ async function saveSettings() { const selectedUsers = getSelectedUsers(); const staticText = document.getElementById('static_text').value.trim(); const fullName = document.getElementById('full_name').checked; - const startHour = parseInt(document.getElementById('start_hour').value); - const endHour = parseInt(document.getElementById('end_hour').value); - const intervalMinutes = parseInt(document.getElementById('interval_minutes').value); + const hour = parseInt(document.getElementById('hour').value); + const minute = parseInt(document.getElementById('minute').value); const schedulerEnabled = document.getElementById('scheduler_enabled').checked; // Валидация @@ -210,23 +207,13 @@ async function saveSettings() { return; } - if (startHour < 0 || startHour > 23) { - showAlert('warning', 'Время начала должно быть от 0 до 23 часов'); + if (hour < 0 || hour > 23) { + showAlert('warning', 'Час должен быть от 0 до 23 часов'); return; } - if (endHour < 0 || endHour > 23) { - showAlert('warning', 'Время окончания должно быть от 0 до 23 часов'); - return; - } - - if (startHour >= endHour) { - showAlert('warning', 'Время начала должно быть раньше времени окончания'); - return; - } - - if (intervalMinutes < 1 || intervalMinutes > 1440) { - showAlert('warning', 'Интервал должен быть от 1 до 1440 минут'); + if (minute < 0 || minute > 59) { + showAlert('warning', 'Минута должна быть от 0 до 59 минут'); return; } @@ -248,14 +235,12 @@ async function saveSettings() { } // Только измененные данные для schedulerData - if (startHour !== originalSettings.start_hour || - endHour !== originalSettings.end_hour || - intervalMinutes !== originalSettings.interval_minutes || + if (hour !== originalSettings.hour || + minute !== originalSettings.minute || schedulerEnabled !== originalSettings.enabled) { postData.schedulerData = { - startTime: startHour.toString(), - endTime: endHour.toString(), - interval_minutes: intervalMinutes.toString(), + hour: hour, + minute: minute, enabled: schedulerEnabled }; } @@ -288,6 +273,9 @@ async function saveSettings() { if (Object.keys(postData.schedulerData).length > 0) { setTimeout(updateSchedulerStatus, 1000); } + if (data.next_run_time) { + document.getElementById('nextRunTime').textContent = data.next_run_time; + } } else { const error = data.message || 'Ошибка сохранения'; showAlert('danger', error); diff --git a/static/js/vk.js b/static/js/vk.js index 7d12f09..d5a142e 100644 --- a/static/js/vk.js +++ b/static/js/vk.js @@ -151,4 +151,42 @@ document.getElementById('base_photo_url').addEventListener('focus', function () if (!this.value) { showAlert('info', 'Формат ID фото: photo_id (например: 7236456789)'); } -}); \ No newline at end of file +}); + +function handleLink() { + const link = prompt('Введите ссылку на фотографию:'); + if (!link) return; + + try { + const url = new URL(link); + const zParam = url.searchParams.get('z'); + + if (!zParam || !zParam.startsWith('photo')) { + alert('Некорректная ссылка на фото ВК'); + return; + } + + const decoded = decodeURIComponent(zParam); + const match = decoded.match(/photo(-?\d+)_(\d+)/); + + if (!match) { + alert('Не удалось разобрать ссылку'); + return; + } + + const groupId = Math.abs(Number(match[1])); + const photoId = Number(match[2]); + + const isConfirmed = window.confirm( + `Применить новые данные?\nГруппа: ${groupId}\nID фото: ${photoId}` + ); + + if (isConfirmed) { + document.getElementById('group_id').value = groupId; + document.getElementById('base_photo_url').value = photoId; + } + + } catch (e) { + alert('Ошибка обработки ссылки'); + } +} \ No newline at end of file diff --git a/templates/index.html b/templates/index.html index ab349ae..48ac7df 100644 --- a/templates/index.html +++ b/templates/index.html @@ -228,12 +228,12 @@
-
Следующий запуск
+
Отображение имен
- {% if exitData.vkPost.scheduler.next_run_time %} - {{ exitData.vkPost.scheduler.next_run_time }} + {% if exitData.vkPost.full_name %} + Полные имена {% else %} - Не запланирован + Короткие имена {% endif %}
@@ -365,12 +365,12 @@
-
Отображение имен
+
Следующая публикация
- {% if exitData.vkPost.full_name %} - Полные имена + {% if exitData.vkPost.scheduler.next_run_time %} + {{ exitData.vkPost.scheduler.next_run_time }} {% else %} - Короткие имена + Не запланирован {% endif %}
diff --git a/templates/posts.html b/templates/posts.html index 49e412f..e6217cf 100644 --- a/templates/posts.html +++ b/templates/posts.html @@ -12,13 +12,16 @@

Управление постами

Создание и планирование публикаций в VK

+
Публикации
-
+
@@ -164,95 +167,50 @@
+
-
-
-
- -
-
-
Временная настройка
-

Посты будут опубликованы в 12:00 ежедневно.
Настройки из расписания будут - проигнорированы!

+ +
+ +
+ + + : +
-
- -
-
- -
- - - :00 + +
+ +
+ +
-
- -
- - - :00 -
-
-
- -
- - -
- Через сколько минут публиковать следующий пост -
-
- - -
- -
- - -
-
- - - {% if data.schedulerStatus.next_run_time %} -
-
-
- -
-
-
Следующая публикация
-

{{ data.schedulerStatus.next_run_time }}

-
-
-
- {% endif %} -
-
-
-
- - -
-
-
-
- -
- Сохраняются: выбранные сотрудники, текст поста, настройки расписания
+ + + {% if data.schedulerStatus.next_run_time %} +
+
+
+ +
+
+
Следующая публикация
+

{{ data.schedulerStatus.next_run_time }}

+
+
+
+ {% endif %}
diff --git a/templates/vk.html b/templates/vk.html index 6465436..7a0bc5e 100644 --- a/templates/vk.html +++ b/templates/vk.html @@ -96,6 +96,9 @@ +
@@ -103,7 +106,7 @@ {% if data.vk_settings %} -
+
Текущие настройки
@@ -123,16 +126,25 @@
ID сообщества
-

-{{ data.vk_settings.group_id }}

+

+ + -{{ data.vk_settings.group_id }} + +

-
ID Базового фото
-

photo-{{ data.vk_settings.group_id }}_{{ - data.vk_settings.base_photo_url }}

+
Базовое фото
+

+ + photo-{{ data.vk_settings.group_id }}_{{ + data.vk_settings.base_photo_url }} + +