release
This commit is contained in:
@@ -332,6 +332,7 @@ def api_vk():
|
|||||||
|
|
||||||
@app.route("/api/posts", methods=["POST", "GET"])
|
@app.route("/api/posts", methods=["POST", "GET"])
|
||||||
def api_posts():
|
def api_posts():
|
||||||
|
response = {"status": "ok"}
|
||||||
match request.method:
|
match request.method:
|
||||||
case "POST":
|
case "POST":
|
||||||
requestData = request.json
|
requestData = request.json
|
||||||
@@ -362,32 +363,34 @@ def api_posts():
|
|||||||
logger.info("Обновление расписания публикации")
|
logger.info("Обновление расписания публикации")
|
||||||
try:
|
try:
|
||||||
scheduler = PostScheduler.query.first()
|
scheduler = PostScheduler.query.first()
|
||||||
startTime = schedulerData.get("startTime", None)
|
hour = schedulerData.get("hour", None)
|
||||||
endTime = schedulerData.get("endTime", None)
|
minute = schedulerData.get("minute", None)
|
||||||
interval_minutes = schedulerData.get("interval_minutes", None)
|
|
||||||
enabled = schedulerData.get("enabled", None)
|
enabled = schedulerData.get("enabled", None)
|
||||||
if scheduler:
|
if scheduler:
|
||||||
if startTime:
|
if hour is not None:
|
||||||
scheduler.start_hour = int(startTime)
|
if scheduler.hour != hour:
|
||||||
if endTime:
|
scheduler.hour = hour
|
||||||
scheduler.end_hour = int(endTime)
|
if minute is not None:
|
||||||
if interval_minutes:
|
if scheduler.minute != minute:
|
||||||
scheduler.interval_minutes = int(interval_minutes)
|
scheduler.minute = minute
|
||||||
if enabled is not None:
|
if enabled is not None:
|
||||||
|
if scheduler.enabled != enabled:
|
||||||
scheduler.enabled = enabled
|
scheduler.enabled = enabled
|
||||||
else:
|
else:
|
||||||
db.session.merge(
|
db.session.merge(
|
||||||
PostScheduler(
|
PostScheduler(
|
||||||
start_hour=int(startTime),
|
hour=int(hour),
|
||||||
end_hour=int(endTime),
|
minute=int(minute),
|
||||||
interval_minutes=int(interval_minutes),
|
|
||||||
enabled=enabled,
|
enabled=enabled,
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
db.session.commit()
|
db.session.commit()
|
||||||
|
enable_publish_job()
|
||||||
|
scheduleInfo = get_scheduler_status()
|
||||||
|
response["next_run_time"] = scheduleInfo.get("next_run_time")
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
logger.error(f"Ошибка при обновлении расписания публикации: {e}")
|
logger.error(f"Ошибка при обновлении расписания публикации: {e}")
|
||||||
return jsonify({"status": "ok"})
|
return jsonify(response)
|
||||||
|
|
||||||
case "GET":
|
case "GET":
|
||||||
queryParams = request.args.to_dict()
|
queryParams = request.args.to_dict()
|
||||||
|
|||||||
@@ -123,9 +123,8 @@ class PostScheduler(db.Model):
|
|||||||
__tablename__ = "post_scheduler"
|
__tablename__ = "post_scheduler"
|
||||||
|
|
||||||
id = db.Column(db.Integer, primary_key=True)
|
id = db.Column(db.Integer, primary_key=True)
|
||||||
start_hour = db.Column(db.Integer)
|
hour = db.Column(db.Integer)
|
||||||
end_hour = db.Column(db.Integer)
|
minute = db.Column(db.Integer)
|
||||||
interval_minutes = db.Column(db.Integer)
|
|
||||||
enabled = db.Column(db.Boolean)
|
enabled = db.Column(db.Boolean)
|
||||||
created_at = db.Column(db.DateTime, default=datetime.now)
|
created_at = db.Column(db.DateTime, default=datetime.now)
|
||||||
updated_at = db.Column(db.DateTime, default=datetime.now, onupdate=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):
|
def toDict(self):
|
||||||
return {
|
return {
|
||||||
"id": self.id,
|
"id": self.id,
|
||||||
"start_hour": self.start_hour,
|
"hour": self.hour,
|
||||||
"end_hour": self.end_hour,
|
"minute": self.minute,
|
||||||
"interval_minutes": self.interval_minutes,
|
|
||||||
"enabled": self.enabled,
|
"enabled": self.enabled,
|
||||||
"created_at": self.created_at.strftime("%Y-%m-%d %H:%M:%S"),
|
"created_at": self.created_at.strftime("%Y-%m-%d %H:%M:%S"),
|
||||||
"updated_at": self.updated_at.strftime("%Y-%m-%d %H:%M:%S"),
|
"updated_at": self.updated_at.strftime("%Y-%m-%d %H:%M:%S"),
|
||||||
|
|||||||
+2
-10
@@ -75,19 +75,11 @@ def enable_publish_job():
|
|||||||
disable_publish_job()
|
disable_publish_job()
|
||||||
return
|
return
|
||||||
|
|
||||||
start_hour = scheduleData.start_hour
|
|
||||||
end_hour = scheduleData.end_hour
|
|
||||||
interval_minutes = scheduleData.interval_minutes
|
|
||||||
|
|
||||||
trigger = CronTrigger(
|
trigger = CronTrigger(
|
||||||
hour="12",
|
hour=f"{scheduleData.hour}",
|
||||||
minute="0",
|
minute=f"{scheduleData.minute}",
|
||||||
day="*",
|
day="*",
|
||||||
)
|
)
|
||||||
# trigger = CronTrigger(
|
|
||||||
# hour=f"{start_hour}-{end_hour - 1}",
|
|
||||||
# minute=f"*/{interval_minutes}",
|
|
||||||
# )
|
|
||||||
|
|
||||||
scheduler.add_job(
|
scheduler.add_job(
|
||||||
vk_publish_job,
|
vk_publish_job,
|
||||||
|
|||||||
@@ -17,7 +17,7 @@
|
|||||||
|
|
||||||
/* Таблица сотрудников */
|
/* Таблица сотрудников */
|
||||||
.table-responsive {
|
.table-responsive {
|
||||||
max-height: 800px;
|
max-height: 575px;
|
||||||
overflow-y: auto;
|
overflow-y: auto;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+18
-30
@@ -20,9 +20,8 @@ function saveOriginalSettings() {
|
|||||||
selected_users: getSelectedUsers(),
|
selected_users: getSelectedUsers(),
|
||||||
static_text: document.getElementById('static_text').value,
|
static_text: document.getElementById('static_text').value,
|
||||||
full_name: document.getElementById('full_name').checked,
|
full_name: document.getElementById('full_name').checked,
|
||||||
start_hour: parseInt(document.getElementById('start_hour').value),
|
hour: parseInt(document.getElementById('hour').value),
|
||||||
end_hour: parseInt(document.getElementById('end_hour').value),
|
minute: parseInt(document.getElementById('minute').value),
|
||||||
interval_minutes: parseInt(document.getElementById('interval_minutes').value),
|
|
||||||
enabled: document.getElementById('scheduler_enabled').checked
|
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 => {
|
formFields.forEach(field => {
|
||||||
const element = document.getElementById(field);
|
const element = document.getElementById(field);
|
||||||
if (element) {
|
if (element) {
|
||||||
@@ -58,9 +57,8 @@ function checkForChanges() {
|
|||||||
selected_users: getSelectedUsers(),
|
selected_users: getSelectedUsers(),
|
||||||
static_text: document.getElementById('static_text').value,
|
static_text: document.getElementById('static_text').value,
|
||||||
full_name: document.getElementById('full_name').checked,
|
full_name: document.getElementById('full_name').checked,
|
||||||
start_hour: parseInt(document.getElementById('start_hour').value),
|
hour: parseInt(document.getElementById('hour').value),
|
||||||
end_hour: parseInt(document.getElementById('end_hour').value),
|
minute: parseInt(document.getElementById('minute').value),
|
||||||
interval_minutes: parseInt(document.getElementById('interval_minutes').value),
|
|
||||||
enabled: document.getElementById('scheduler_enabled').checked
|
enabled: document.getElementById('scheduler_enabled').checked
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -194,9 +192,8 @@ async function saveSettings() {
|
|||||||
const selectedUsers = getSelectedUsers();
|
const selectedUsers = getSelectedUsers();
|
||||||
const staticText = document.getElementById('static_text').value.trim();
|
const staticText = document.getElementById('static_text').value.trim();
|
||||||
const fullName = document.getElementById('full_name').checked;
|
const fullName = document.getElementById('full_name').checked;
|
||||||
const startHour = parseInt(document.getElementById('start_hour').value);
|
const hour = parseInt(document.getElementById('hour').value);
|
||||||
const endHour = parseInt(document.getElementById('end_hour').value);
|
const minute = parseInt(document.getElementById('minute').value);
|
||||||
const intervalMinutes = parseInt(document.getElementById('interval_minutes').value);
|
|
||||||
const schedulerEnabled = document.getElementById('scheduler_enabled').checked;
|
const schedulerEnabled = document.getElementById('scheduler_enabled').checked;
|
||||||
|
|
||||||
// Валидация
|
// Валидация
|
||||||
@@ -210,23 +207,13 @@ async function saveSettings() {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (startHour < 0 || startHour > 23) {
|
if (hour < 0 || hour > 23) {
|
||||||
showAlert('warning', 'Время начала должно быть от 0 до 23 часов');
|
showAlert('warning', 'Час должен быть от 0 до 23 часов');
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (endHour < 0 || endHour > 23) {
|
if (minute < 0 || minute > 59) {
|
||||||
showAlert('warning', 'Время окончания должно быть от 0 до 23 часов');
|
showAlert('warning', 'Минута должна быть от 0 до 59 минут');
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (startHour >= endHour) {
|
|
||||||
showAlert('warning', 'Время начала должно быть раньше времени окончания');
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (intervalMinutes < 1 || intervalMinutes > 1440) {
|
|
||||||
showAlert('warning', 'Интервал должен быть от 1 до 1440 минут');
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -248,14 +235,12 @@ async function saveSettings() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Только измененные данные для schedulerData
|
// Только измененные данные для schedulerData
|
||||||
if (startHour !== originalSettings.start_hour ||
|
if (hour !== originalSettings.hour ||
|
||||||
endHour !== originalSettings.end_hour ||
|
minute !== originalSettings.minute ||
|
||||||
intervalMinutes !== originalSettings.interval_minutes ||
|
|
||||||
schedulerEnabled !== originalSettings.enabled) {
|
schedulerEnabled !== originalSettings.enabled) {
|
||||||
postData.schedulerData = {
|
postData.schedulerData = {
|
||||||
startTime: startHour.toString(),
|
hour: hour,
|
||||||
endTime: endHour.toString(),
|
minute: minute,
|
||||||
interval_minutes: intervalMinutes.toString(),
|
|
||||||
enabled: schedulerEnabled
|
enabled: schedulerEnabled
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
@@ -288,6 +273,9 @@ async function saveSettings() {
|
|||||||
if (Object.keys(postData.schedulerData).length > 0) {
|
if (Object.keys(postData.schedulerData).length > 0) {
|
||||||
setTimeout(updateSchedulerStatus, 1000);
|
setTimeout(updateSchedulerStatus, 1000);
|
||||||
}
|
}
|
||||||
|
if (data.next_run_time) {
|
||||||
|
document.getElementById('nextRunTime').textContent = data.next_run_time;
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
const error = data.message || 'Ошибка сохранения';
|
const error = data.message || 'Ошибка сохранения';
|
||||||
showAlert('danger', error);
|
showAlert('danger', error);
|
||||||
|
|||||||
@@ -152,3 +152,41 @@ document.getElementById('base_photo_url').addEventListener('focus', function ()
|
|||||||
showAlert('info', 'Формат ID фото: photo_id (например: 7236456789)');
|
showAlert('info', 'Формат ID фото: photo_id (например: 7236456789)');
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
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('Ошибка обработки ссылки');
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -228,12 +228,12 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="col-6">
|
<div class="col-6">
|
||||||
<div class="small text-muted">Следующий запуск</div>
|
<div class="small text-muted">Отображение имен</div>
|
||||||
<div class="fw-semibold">
|
<div class="fw-semibold">
|
||||||
{% if exitData.vkPost.scheduler.next_run_time %}
|
{% if exitData.vkPost.full_name %}
|
||||||
{{ exitData.vkPost.scheduler.next_run_time }}
|
Полные имена
|
||||||
{% else %}
|
{% else %}
|
||||||
Не запланирован
|
Короткие имена
|
||||||
{% endif %}
|
{% endif %}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -365,12 +365,12 @@
|
|||||||
<div class="col-6">
|
<div class="col-6">
|
||||||
<div class="card bg-light">
|
<div class="card bg-light">
|
||||||
<div class="card-body py-2">
|
<div class="card-body py-2">
|
||||||
<div class="small text-muted">Отображение имен</div>
|
<div class="small text-muted">Следующая публикация</div>
|
||||||
<div class="fw-semibold">
|
<div class="fw-semibold">
|
||||||
{% if exitData.vkPost.full_name %}
|
{% if exitData.vkPost.scheduler.next_run_time %}
|
||||||
Полные имена
|
{{ exitData.vkPost.scheduler.next_run_time }}
|
||||||
{% else %}
|
{% else %}
|
||||||
Короткие имена
|
Не запланирован
|
||||||
{% endif %}
|
{% endif %}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
+27
-69
@@ -12,13 +12,16 @@
|
|||||||
<h2 class="mb-1"><i class="bi bi-megaphone-fill text-primary me-2"></i>Управление постами</h2>
|
<h2 class="mb-1"><i class="bi bi-megaphone-fill text-primary me-2"></i>Управление постами</h2>
|
||||||
<p class="text-muted mb-0">Создание и планирование публикаций в VK</p>
|
<p class="text-muted mb-0">Создание и планирование публикаций в VK</p>
|
||||||
</div>
|
</div>
|
||||||
|
<button type="button" class="btn btn-success btn-lg px-5" onclick="saveSettings()">
|
||||||
|
<i class="bi bi-save me-2"></i>Сохранить все настройки
|
||||||
|
</button>
|
||||||
<div class="badge bg-primary fs-6 px-3 py-2">
|
<div class="badge bg-primary fs-6 px-3 py-2">
|
||||||
<i class="bi bi-calendar-week me-1"></i>Публикации
|
<i class="bi bi-calendar-week me-1"></i>Публикации
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- Основной контент -->
|
<!-- Основной контент -->
|
||||||
<div class="row g-4">
|
<div class="row g-4 mb-3">
|
||||||
<!-- Левая колонка: Сотрудники -->
|
<!-- Левая колонка: Сотрудники -->
|
||||||
<div class="col-lg-7">
|
<div class="col-lg-7">
|
||||||
<div class="card h-100">
|
<div class="card h-100">
|
||||||
@@ -164,74 +167,46 @@
|
|||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
<div class="card-body">
|
<div class="card-body">
|
||||||
|
<div class="row g-3 align-items-start">
|
||||||
|
|
||||||
<div class="alert alert-danger">
|
<!-- Время запуска -->
|
||||||
<div class="d-flex">
|
<div class="col-12 col-md-4">
|
||||||
<div class="me-3">
|
<label class="form-label fw-semibold mb-1">Время запуска</label>
|
||||||
<i class="bi bi-exclamation-triangle fs-5"></i>
|
<div class="input-group input-group-sm">
|
||||||
</div>
|
<span class="input-group-text"><i class="bi bi-alarm"></i></span>
|
||||||
<div>
|
<input type="number" class="form-control" id="hour" min="0" max="23"
|
||||||
<h6 class="alert-heading mb-1">Временная настройка</h6>
|
value="{{ data.schedulerSettings.hour if data.schedulerSettings else 12 }}">
|
||||||
<p class="mb-0">Посты будут опубликованы в 12:00 ежедневно.<br>Настройки из расписания будут
|
<span class="input-group-text">:</span>
|
||||||
проигнорированы!</p>
|
<input type="number" class="form-control" id="minute" min="0" max="59"
|
||||||
</div>
|
value="{{ data.schedulerSettings.minute if data.schedulerSettings else 0 }}">
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- Время работы -->
|
<!-- Статус планировщика -->
|
||||||
<div class="row g-3 mb-3">
|
<div class="col-12 col-md-8">
|
||||||
<div class="col-md-6">
|
<label class="form-label fw-semibold mb-1">Статус планировщика</label>
|
||||||
<label class="form-label fw-semibold">Начало публикации</label>
|
<div class="form-check form-switch d-flex align-items-center gap-2 p-0">
|
||||||
<div class="input-group">
|
<input class="form-check-input m-0" type="checkbox" role="switch" id="scheduler_enabled" {%
|
||||||
<span class="input-group-text"><i class="bi bi-sun"></i></span>
|
if data.schedulerSettings and data.schedulerSettings.enabled %}checked{% endif %}>
|
||||||
<input type="number" class="form-control" id="start_hour" min="0" max="23"
|
|
||||||
value="{{ data.schedulerSettings.start_hour if data.schedulerSettings else 9 }}">
|
|
||||||
<span class="input-group-text">:00</span>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="col-md-6">
|
|
||||||
<label class="form-label fw-semibold">Конец публикации</label>
|
|
||||||
<div class="input-group">
|
|
||||||
<span class="input-group-text"><i class="bi bi-moon"></i></span>
|
|
||||||
<input type="number" class="form-control" id="end_hour" min="0" max="23"
|
|
||||||
value="{{ data.schedulerSettings.end_hour if data.schedulerSettings else 21 }}">
|
|
||||||
<span class="input-group-text">:00</span>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<!-- Интервал -->
|
|
||||||
<div class="mb-3">
|
|
||||||
<label class="form-label fw-semibold">Интервал публикации (минут)</label>
|
|
||||||
<input type="number" class="form-control" id="interval_minutes" min="1" max="1440"
|
|
||||||
value="{{ data.schedulerSettings.interval_minutes if data.schedulerSettings else 60 }}">
|
|
||||||
<div class="form-text">
|
|
||||||
Через сколько минут публиковать следующий пост
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<!-- Включить/выключить -->
|
|
||||||
<div class="mb-4">
|
|
||||||
<label class="form-label fw-semibold">Статус планировщика</label>
|
|
||||||
<div class="form-check form-switch d-flex justify-content-left gap-2 p-0">
|
|
||||||
<input class="form-check-input m-0" type="checkbox" role="switch" id="scheduler_enabled" {% if
|
|
||||||
data.schedulerSettings and data.schedulerSettings.enabled %}checked{% endif %}>
|
|
||||||
<label class="form-check-label mb-0" for="scheduler_enabled">
|
<label class="form-check-label mb-0" for="scheduler_enabled">
|
||||||
Автоматическая публикация по расписанию
|
Автоматическая публикация
|
||||||
</label>
|
</label>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
<!-- Информация о следующем запуске -->
|
<!-- Информация о следующем запуске -->
|
||||||
{% if data.schedulerStatus.next_run_time %}
|
{% if data.schedulerStatus.next_run_time %}
|
||||||
<div class="alert alert-info">
|
<div class="alert alert-success shadow mx-3">
|
||||||
<div class="d-flex">
|
<div class="d-flex">
|
||||||
<div class="me-3">
|
<div class="me-3">
|
||||||
<i class="bi bi-info-circle fs-5"></i>
|
<i class="bi bi-info-circle fs-5"></i>
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
<h6 class="alert-heading mb-1">Следующая публикация</h6>
|
<h6 class="alert-heading mb-1">Следующая публикация</h6>
|
||||||
<p class="mb-0">{{ data.schedulerStatus.next_run_time }}</p>
|
<p class="mb-0" id="nextRunTime">{{ data.schedulerStatus.next_run_time }}</p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -239,23 +214,6 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
|
||||||
|
|
||||||
<!-- Кнопка сохранения -->
|
|
||||||
<div class="row mt-4">
|
|
||||||
<div class="col-12">
|
|
||||||
<div class="card">
|
|
||||||
<div class="card-body text-center py-3">
|
|
||||||
<button type="button" class="btn btn-success btn-lg px-5" onclick="saveSettings()">
|
|
||||||
<i class="bi bi-save me-2"></i>Сохранить все настройки
|
|
||||||
</button>
|
|
||||||
<div class="form-text mt-2">
|
|
||||||
Сохраняются: выбранные сотрудники, текст поста, настройки расписания
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<!-- Контейнер для уведомлений -->
|
<!-- Контейнер для уведомлений -->
|
||||||
<div id="alertContainer" class="alert-fixed"></div>
|
<div id="alertContainer" class="alert-fixed"></div>
|
||||||
|
|||||||
+17
-5
@@ -96,6 +96,9 @@
|
|||||||
<button type="button" class="btn btn-primary" onclick="saveVkSettings()" id="saveButton">
|
<button type="button" class="btn btn-primary" onclick="saveVkSettings()" id="saveButton">
|
||||||
<i class="bi bi-save me-1"></i>Сохранить настройки
|
<i class="bi bi-save me-1"></i>Сохранить настройки
|
||||||
</button>
|
</button>
|
||||||
|
<button type="button" class="btn btn-outline-success" onclick="handleLink()" id="linkButton">
|
||||||
|
<i class="bi bi-link me-1"></i>Получить данные из ссылки на фото
|
||||||
|
</button>
|
||||||
</div>
|
</div>
|
||||||
</form>
|
</form>
|
||||||
</div>
|
</div>
|
||||||
@@ -103,7 +106,7 @@
|
|||||||
|
|
||||||
<!-- Информация о текущих настройках -->
|
<!-- Информация о текущих настройках -->
|
||||||
{% if data.vk_settings %}
|
{% if data.vk_settings %}
|
||||||
<div class="card mt-4 fade-in">
|
<div class="card my-4 fade-in">
|
||||||
<div class="card-header bg-success bg-opacity-10 text-success">
|
<div class="card-header bg-success bg-opacity-10 text-success">
|
||||||
<h6 class="mb-0"><i class="bi bi-check-circle me-2"></i>Текущие настройки</h6>
|
<h6 class="mb-0"><i class="bi bi-check-circle me-2"></i>Текущие настройки</h6>
|
||||||
</div>
|
</div>
|
||||||
@@ -123,16 +126,25 @@
|
|||||||
<div class="card bg-light">
|
<div class="card bg-light">
|
||||||
<div class="card-body">
|
<div class="card-body">
|
||||||
<h6 class="card-title"><i class="bi bi-people me-2"></i>ID сообщества</h6>
|
<h6 class="card-title"><i class="bi bi-people me-2"></i>ID сообщества</h6>
|
||||||
<p class="card-text">-{{ data.vk_settings.group_id }}</p>
|
<p class="card-text">
|
||||||
|
<a href="https://vk.com/club{{ data.vk_settings.group_id }}" target="_blank">
|
||||||
|
<i class="bi bi-link me-1"></i>-{{ data.vk_settings.group_id }}
|
||||||
|
</a>
|
||||||
|
</p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="col-md-4">
|
<div class="col-md-4">
|
||||||
<div class="card bg-light">
|
<div class="card bg-light">
|
||||||
<div class="card-body">
|
<div class="card-body">
|
||||||
<h6 class="card-title"><i class="bi bi-image me-2"></i>ID Базового фото</h6>
|
<h6 class="card-title"><i class="bi bi-image me-2"></i>Базовое фото</h6>
|
||||||
<p class="card-text">photo-{{ data.vk_settings.group_id }}_{{
|
<p class="card-text">
|
||||||
data.vk_settings.base_photo_url }}</p>
|
<a href="https://vk.com/photo-{{ data.vk_settings.group_id }}_{{ data.vk_settings.base_photo_url }}"
|
||||||
|
target="_blank">
|
||||||
|
<i class="bi bi-link me-1"></i>photo-{{ data.vk_settings.group_id }}_{{
|
||||||
|
data.vk_settings.base_photo_url }}
|
||||||
|
</a>
|
||||||
|
</p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
Reference in New Issue
Block a user