полный рефакторинг всей системы
All checks were successful
continuous-integration/drone/push Build is passing
All checks were successful
continuous-integration/drone/push Build is passing
This commit is contained in:
@@ -3,28 +3,30 @@
|
||||
<div
|
||||
class="bg-white flex flex-col lg:flex-row justify-between items-center p-3 lg:p-5 dark:bg-gray-800 gap-3 lg:gap-4"
|
||||
>
|
||||
<!-- Блок 1: Поиск + Фильтр (всегда в ряд) -->
|
||||
<div class="flex flex-row w-full lg:w-auto">
|
||||
<div class="relative w-2/3">
|
||||
<img
|
||||
v-if="isDarkMode"
|
||||
v-if="isDark"
|
||||
src="https://img.icons8.com/?size=100&id=WwWusvLMTFd7&format=png&color=000000"
|
||||
class="absolute top-1/2 -translate-y-1/2 left-3 h-5"
|
||||
alt=""
|
||||
/>
|
||||
<img
|
||||
v-else
|
||||
src="https://img.icons8.com/?size=100&id=zR5EBMqZTIBz&format=png&color=000000"
|
||||
class="absolute top-1/2 -translate-y-1/2 left-3 h-5"
|
||||
alt=""
|
||||
/>
|
||||
<input
|
||||
v-model="poisk"
|
||||
v-model="searchQuery"
|
||||
type="text"
|
||||
placeholder="Поиск..."
|
||||
class="w-full h-12 dark:bg-gray-900 border-slate-100 shadow rounded-xl p-3 pl-11"
|
||||
/>
|
||||
</div>
|
||||
<select
|
||||
@change="onfilterItems($event.target.value)"
|
||||
v-model="activeCategory"
|
||||
@change="onFilterChange"
|
||||
class="w-1/3 h-12 dark:bg-gray-900 border-slate-100 shadow rounded-xl p-3 ml-2"
|
||||
>
|
||||
<option value="all">Все</option>
|
||||
@@ -38,7 +40,6 @@
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<!-- Блок 2: URL + Категория + Кнопка (всегда в ряд) -->
|
||||
<div
|
||||
class="flex flex-row w-full lg:w-auto gap-2 p-2 bg-gray-50 dark:bg-gray-700 rounded-xl border border-gray-200 dark:border-gray-600"
|
||||
>
|
||||
@@ -64,6 +65,7 @@
|
||||
</select>
|
||||
|
||||
<button
|
||||
type="button"
|
||||
@click="addSource"
|
||||
class="w-20 h-12 bg-green-600 text-white px-2 rounded-xl shadow hover:bg-green-700 cursor-pointer whitespace-nowrap"
|
||||
>
|
||||
@@ -72,10 +74,13 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Список источников -->
|
||||
<div class="p-4 grid gap-2 grid-cols-1 xl:grid-cols-2 2xl:grid-cols-3">
|
||||
<div v-for="source in filteredSources" :key="source.url" class="mb-4 hover:-translate-y-2 hover:shadow-2xl transition">
|
||||
<Istochnik_one_kard
|
||||
<div
|
||||
v-for="source in filteredSources"
|
||||
:key="source.url"
|
||||
class="mb-4 hover:-translate-y-2 hover:shadow-2xl transition"
|
||||
>
|
||||
<SourceCard
|
||||
:source="source"
|
||||
@sourceStarted="handleSourceStarted"
|
||||
@sourceDeleted="handleSourceDeleted"
|
||||
@@ -86,92 +91,77 @@
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { ref, onMounted, computed } from "vue";
|
||||
import axios from "axios";
|
||||
import Istochnik_one_kard from "./Istochnik_one_kard.vue";
|
||||
import { ref, onMounted, computed } from 'vue'
|
||||
import SourceCard from './Istochnik_one_kard.vue'
|
||||
import { useDarkMode } from '@/composables/useDarkMode.js'
|
||||
import { fetchCategories, fetchSources, addSource as apiAddSource } from '@/services/sourceService.js'
|
||||
|
||||
const isDarkMode = ref(false);
|
||||
const newSourceUrl = ref("");
|
||||
const newSourceCategory = ref("");
|
||||
const categories = ref([]);
|
||||
const poisk = ref("");
|
||||
const sources = ref([]);
|
||||
const { isDark } = useDarkMode()
|
||||
|
||||
|
||||
const fetchCategories = async () => {
|
||||
try {
|
||||
const data = await axios.get(
|
||||
"https://allowlgroup.ru/api/8001/categories_promt",
|
||||
);
|
||||
categories.value = data.data;
|
||||
} catch (err) {
|
||||
console.error("Ошибка загрузки категорий:", err);
|
||||
}
|
||||
};
|
||||
|
||||
const fetchSources = async (category) => {
|
||||
try {
|
||||
const data = await axios.get(`https://allowlgroup.ru/api/8001/all_sources`, {
|
||||
params: { category }
|
||||
});
|
||||
sources.value = data.data.sources || [];
|
||||
} catch (err) {
|
||||
console.error("Ошибка загрузки источников:", err);
|
||||
}
|
||||
};
|
||||
const newSourceUrl = ref('')
|
||||
const newSourceCategory = ref('')
|
||||
const categories = ref([])
|
||||
const searchQuery = ref('')
|
||||
const sources = ref([])
|
||||
const activeCategory = ref('all')
|
||||
|
||||
const filteredSources = computed(() => {
|
||||
if (!poisk.value) return sources.value;
|
||||
if (!searchQuery.value) return sources.value
|
||||
const q = searchQuery.value.toLowerCase()
|
||||
return sources.value.filter(
|
||||
(source) =>
|
||||
source.url.toLowerCase().includes(poisk.value.toLowerCase()) ||
|
||||
source.promt.toLowerCase().includes(poisk.value.toLowerCase()),
|
||||
);
|
||||
});
|
||||
source.url.toLowerCase().includes(q) ||
|
||||
source.promt.toLowerCase().includes(q),
|
||||
)
|
||||
})
|
||||
|
||||
const addSource = async () => {
|
||||
async function loadCategories() {
|
||||
try {
|
||||
categories.value = await fetchCategories()
|
||||
} catch (err) {
|
||||
console.error('Ошибка загрузки категорий:', err)
|
||||
}
|
||||
}
|
||||
|
||||
async function loadSources(category = 'all') {
|
||||
try {
|
||||
sources.value = await fetchSources(category)
|
||||
} catch (err) {
|
||||
console.error('Ошибка загрузки источников:', err)
|
||||
}
|
||||
}
|
||||
|
||||
async function addSource() {
|
||||
if (!newSourceUrl.value.trim() || !newSourceCategory.value) {
|
||||
alert("Заполните все поля");
|
||||
return;
|
||||
alert('Заполните все поля')
|
||||
return
|
||||
}
|
||||
|
||||
try {
|
||||
await axios.post("https://allowlgroup.ru/api/8001/add_sources", {
|
||||
url: newSourceUrl.value,
|
||||
promt: newSourceCategory.value,
|
||||
});
|
||||
newSourceUrl.value = "";
|
||||
newSourceCategory.value = "";
|
||||
fetchSources(); // Обновляем список после добавления
|
||||
await apiAddSource(newSourceUrl.value, newSourceCategory.value)
|
||||
newSourceUrl.value = ''
|
||||
newSourceCategory.value = ''
|
||||
await loadSources(activeCategory.value)
|
||||
} catch (err) {
|
||||
console.error("Ошибка добавления источника:", err);
|
||||
alert("Ошибка при добавлении источника");
|
||||
console.error('Ошибка добавления источника:', err)
|
||||
alert('Ошибка при добавлении источника')
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
const onfilterItems = (filterValue) => {
|
||||
fetchSources(filterValue);
|
||||
};
|
||||
function onFilterChange() {
|
||||
loadSources(activeCategory.value)
|
||||
}
|
||||
|
||||
const handleSourceStarted = (url) => {
|
||||
console.log("Парсинг запущен для:", url);
|
||||
};
|
||||
function handleSourceStarted(url) {
|
||||
console.log('Парсинг запущен для:', url)
|
||||
}
|
||||
|
||||
const handleSourceDeleted = (deletedUrl) => {
|
||||
sources.value = sources.value.filter((source) => source.url !== deletedUrl);
|
||||
};
|
||||
function handleSourceDeleted(deletedUrl) {
|
||||
sources.value = sources.value.filter((source) => source.url !== deletedUrl)
|
||||
}
|
||||
|
||||
onMounted(() => {
|
||||
isDarkMode.value = document.documentElement.classList.contains("dark");
|
||||
const mutationObserver = new MutationObserver(() => {
|
||||
isDarkMode.value = document.documentElement.classList.contains("dark");
|
||||
});
|
||||
mutationObserver.observe(document.documentElement, {
|
||||
attributes: true,
|
||||
attributeFilter: ["class"],
|
||||
});
|
||||
|
||||
fetchCategories();
|
||||
fetchSources("all");
|
||||
});
|
||||
loadCategories()
|
||||
loadSources('all')
|
||||
})
|
||||
</script>
|
||||
|
||||
Reference in New Issue
Block a user