Files
DLE/frontend/src/views/smartcontracts/DleManagementView.vue
2026-03-01 22:03:48 +03:00

499 lines
11 KiB
Vue
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.

<!--
Copyright (c) 2024-2026 Тарабанов Александр Викторович
All rights reserved.
This software is proprietary and confidential.
Unauthorized copying, modification, or distribution is prohibited.
For licensing inquiries: info@hb3-accelerator.com
Website: https://hb3-accelerator.com
GitHub: https://github.com/VC-HB3-Accelerator
-->
<template>
<BaseLayout
:is-authenticated="isAuthenticated"
:identities="identities"
:token-balances="tokenBalances"
:is-loading-tokens="isLoadingTokens"
@auth-action-completed="$emit('auth-action-completed')"
>
<div class="dle-management">
<!-- Форма добавления DLE -->
<div class="add-dle-form">
<div class="form-header">
<h4> Добавить новый DLE</h4>
</div>
<div class="form-content">
<div class="form-group">
<label for="dleLink">Ссылка на DLE контракт:</label>
<input
type="text"
id="dleLink"
v-model="newDle.link"
class="form-control"
placeholder="https://sepolia.etherscan.io/address/0x..."
>
<small class="form-help">Вставьте ссылку на Etherscan или другой блокчейн-эксплорер</small>
</div>
<div class="form-group">
<label for="dleName">Название DLE:</label>
<input
type="text"
id="dleName"
v-model="newDle.name"
class="form-control"
placeholder="Название DLE"
>
</div>
<div class="form-group">
<label for="dleDescription">Описание:</label>
<textarea
id="dleDescription"
v-model="newDle.description"
class="form-control"
rows="3"
placeholder="Краткое описание DLE..."
></textarea>
</div>
<div class="form-actions">
<button
class="btn btn-primary"
@click="addDle"
:disabled="!isFormValid || isAdding"
>
<i class="fas fa-plus"></i>
{{ isAdding ? 'Добавление...' : 'Добавить DLE' }}
</button>
</div>
</div>
</div>
<!-- Список добавленных DLE -->
<div class="dles-list">
<div class="list-header">
<h4>📋 Добавленные DLE</h4>
</div>
<div v-if="dles.length === 0" class="no-dles">
<p>Добавленных DLE пока нет</p>
<p>Используйте форму выше для добавления первого DLE</p>
</div>
<div v-else class="dles-grid">
<div
v-for="dle in dles"
:key="dle.id"
class="dle-card"
>
<div class="dle-header">
<h5>{{ dle.name }}</h5>
<span class="dle-status">Добавлен</span>
</div>
<div class="dle-details">
<div class="detail-item">
<strong>Описание:</strong> {{ dle.description }}
</div>
<div class="detail-item">
<strong>Ссылка:</strong>
<a :href="dle.link" target="_blank" class="dle-link">
{{ shortenUrl(dle.link) }}
</a>
</div>
<div class="detail-item">
<strong>Добавлен:</strong> {{ formatDate(dle.addedAt) }}
</div>
</div>
<div class="dle-actions">
<button
class="btn btn-sm btn-primary"
@click="openDle(dle.link)"
>
<i class="fas fa-external-link-alt"></i> Открыть
</button>
<button
class="btn btn-sm btn-danger"
@click="removeDle(dle.id)"
>
<i class="fas fa-trash"></i> Удалить
</button>
</div>
</div>
</div>
</div>
</div>
</BaseLayout>
</template>
<script setup>
import { ref, computed, onMounted, defineProps, defineEmits } from 'vue';
import { useRouter } from 'vue-router';
import { useAuthContext } from '@/composables/useAuth';
import BaseLayout from '../../components/BaseLayout.vue';
const props = defineProps({
isAuthenticated: Boolean,
identities: Array,
tokenBalances: Object,
isLoadingTokens: Boolean
});
const emit = defineEmits(['auth-action-completed']);
const router = useRouter();
const { address } = useAuthContext();
// Подписываемся на централизованные события очистки и обновления данных
onMounted(() => {
window.addEventListener('clear-application-data', () => {
console.log('[DleManagementView] Clearing DLE management data');
// Очищаем данные при выходе из системы
dles.value = [];
});
window.addEventListener('refresh-application-data', () => {
console.log('[DleManagementView] Refreshing DLE management data');
loadDleList(); // Обновляем данные при входе в систему
});
});
// Состояние формы
const isAdding = ref(false);
// Новый DLE
const newDle = ref({
link: '',
name: '',
description: ''
});
// Список DLE
const dles = ref([]);
// Вычисляемые свойства
const isFormValid = computed(() => {
return newDle.value.link && newDle.value.name;
});
// Функции
function shortenUrl(url) {
if (!url) return '';
try {
const urlObj = new URL(url);
return `${urlObj.hostname}${urlObj.pathname.substring(0, 20)}...`;
} catch {
return url.substring(0, 50) + '...';
}
}
function formatDate(date) {
if (!date) return '';
return new Date(date).toLocaleDateString('ru-RU', {
year: 'numeric',
month: 'long',
day: 'numeric',
hour: '2-digit',
minute: '2-digit'
});
}
function addDle() {
if (!isFormValid.value) {
alert('Пожалуйста, заполните все обязательные поля');
return;
}
isAdding.value = true;
try {
// Создаем новый DLE
const dle = {
id: Date.now(),
link: newDle.value.link,
name: newDle.value.name,
description: newDle.value.description,
addedAt: new Date().toISOString()
};
// Добавляем в список
dles.value.unshift(dle);
// Сохраняем в localStorage
saveDlesToStorage();
// Сбрасываем форму
newDle.value = {
link: '',
name: '',
description: ''
};
alert('✅ DLE успешно добавлен!');
} catch (error) {
console.error('Ошибка при добавлении DLE:', error);
alert('❌ Ошибка при добавлении DLE: ' + error.message);
} finally {
isAdding.value = false;
}
}
function removeDle(dleId) {
if (!confirm('Удалить этот DLE?')) return;
try {
dles.value = dles.value.filter(dle => dle.id !== dleId);
saveDlesToStorage();
alert('✅ DLE успешно удален!');
} catch (error) {
console.error('Ошибка при удалении DLE:', error);
alert('❌ Ошибка при удалении DLE: ' + error.message);
}
}
function openDle(link) {
window.open(link, '_blank');
}
function saveDlesToStorage() {
try {
localStorage.setItem('admin-dles', JSON.stringify(dles.value));
} catch (error) {
console.error('Ошибка при сохранении DLE:', error);
}
}
function loadDlesFromStorage() {
try {
const saved = localStorage.getItem('admin-dles');
if (saved) {
dles.value = JSON.parse(saved);
}
} catch (error) {
console.error('Ошибка при загрузке DLE:', error);
}
}
onMounted(() => {
loadDlesFromStorage();
});
</script>
<style scoped>
.dle-management {
padding: 1rem;
}
.management-header {
margin-bottom: 2rem;
text-align: center;
}
.management-header h3 {
color: var(--color-primary);
margin-bottom: 0.5rem;
}
.add-dle-form {
background: #f8f9fa;
border-radius: 8px;
padding: 1.5rem;
margin-bottom: 2rem;
max-width: 600px;
margin-left: auto;
margin-right: auto;
}
.form-header {
margin-bottom: 1rem;
}
.form-header h4 {
margin: 0;
color: var(--color-primary);
}
.form-content {
display: flex;
flex-direction: column;
gap: 1rem;
}
.form-group {
display: flex;
flex-direction: column;
gap: 0.5rem;
}
.form-group label {
font-weight: 600;
color: #333;
}
.form-control {
padding: 0.75rem;
border: 1px solid #ddd;
border-radius: 4px;
font-size: 1rem;
}
.form-control:focus {
outline: none;
border-color: var(--color-primary);
box-shadow: 0 0 0 2px rgba(0, 123, 255, 0.25);
}
.form-help {
color: #666;
font-size: 0.875rem;
}
.form-actions {
margin-top: 1rem;
}
.btn {
padding: 0.75rem 1.5rem;
border: none;
border-radius: 4px;
font-size: 1rem;
cursor: pointer;
transition: all 0.2s;
display: inline-flex;
align-items: center;
gap: 0.5rem;
}
.btn-primary {
background: var(--color-primary);
color: white;
}
.btn-primary:hover:not(:disabled) {
background: #0056b3;
}
.btn-primary:disabled {
opacity: 0.6;
cursor: not-allowed;
}
.btn-danger {
background: #dc3545;
color: white;
}
.btn-danger:hover {
background: #c82333;
}
.dles-list {
margin-top: 2rem;
}
.list-header {
margin-bottom: 1rem;
}
.list-header h4 {
color: var(--color-primary);
margin: 0;
}
.no-dles {
text-align: center;
padding: 2rem;
color: #666;
}
.dles-grid {
display: grid;
grid-template-columns: repeat(auto-fill, minmax(350px, 1fr));
gap: 1.5rem;
}
/* Мобильная адаптивность */
@media (max-width: 768px) {
.dles-grid {
grid-template-columns: 1fr;
gap: 1rem;
}
.dle-card {
padding: 1rem;
}
.dle-header h5 {
font-size: 1.1rem;
}
.detail-item {
font-size: 0.9rem;
}
}
.dle-card {
background: white;
border-radius: 8px;
padding: 1.5rem;
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
border: 1px solid #e9ecef;
}
.dle-header {
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 1rem;
}
.dle-header h5 {
margin: 0;
color: var(--color-primary);
}
.dle-status {
background: #28a745;
color: white;
padding: 0.25rem 0.75rem;
border-radius: 12px;
font-size: 0.875rem;
}
.dle-details {
margin-bottom: 1rem;
}
.detail-item {
margin-bottom: 0.5rem;
}
.detail-item strong {
color: #333;
}
.dle-link {
color: var(--color-primary);
text-decoration: none;
}
.dle-link:hover {
text-decoration: underline;
}
.dle-actions {
display: flex;
gap: 0.5rem;
}
.btn-sm {
padding: 0.5rem 1rem;
font-size: 0.875rem;
}
</style>