/
Matvey1337
/
it
Обзор
Документация
Войти
/
Matvey1337
/
it
Код
Запросы
0
Задачи
Вики
Пакеты
0
Релизы
0
CI/CD
Аналитика
Безопасность
master
index.html
316 строк
7 KB
Matvey1337
Initial commit
08 май 2026, 21:04
08 май 2026, 21:04
5241099
Код
Авторство
О чём код?
<!DOCTYPE html> <html lang="ru"> <head> <meta charset="UTF-8" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" /> <title>Список студий</title> <style> body { font-family: Arial, sans-serif; background: #f3f3f3; margin: 0; padding: 20px; } .wrapper { max-width: 1100px; margin: 0 auto; background: #fff; padding: 20px; border-radius: 10px; } h1 { margin-bottom: 20px; font-size: 24px; } table { width: 100%; border-collapse: collapse; background: white; } th, td { border-bottom: 1px solid #ddd; padding: 10px; text-align: left; } th { background: #f7f7f7; } .logo { width: 36px; height: 36px; border-radius: 6px; vertical-align: middle; margin-right: 8px; object-fit: cover; } .place { display: inline-block; min-width: 28px; text-align: center; padding: 4px 8px; border-radius: 6px; background: #eaeaea; } .top-1 { background: gold; } .top-2 { background: silver; } .top-3 { background: #cd7f32; color: white; } .controls { margin-top: 20px; text-align: center; } button { padding: 10px 18px; border: 1px solid #ccc; background: white; border-radius: 8px; cursor: pointer; } button:disabled { opacity: 0.6; cursor: not-allowed; } .selected-box { margin-top: 25px; padding: 15px; background: #f8f8f8; border-radius: 8px; } .selected-list { display: flex; flex-wrap: wrap; gap: 10px; margin-top: 10px; } .selected-item { background: #e9e9e9; padding: 6px 10px; border-radius: 16px; display: flex; align-items: center; gap: 8px; } .small-logo { width: 20px; height: 20px; border-radius: 4px; object-fit: cover; } .delete-btn { border: none; background: transparent; color: red; font-size: 16px; cursor: pointer; padding: 0; } .status { margin: 15px 0; } @media (max-width: 768px) { th, td { font-size: 12px; padding: 8px; } h1 { font-size: 20px; } } </style> </head> <body> <div id="app" class="wrapper"> <h1>Рейтинг студий разработки</h1> <div class="status" v-if="loading">Загрузка данных...</div> <table v-if="studios.length > 0"> <thead> <tr> <th> <input type="checkbox" @change="toggleAll($event)"> </th> <th>Место</th> <th>Компания</th> <th>Баллы</th> <th>Кейсы</th> <th>Выручка</th> </tr> </thead> <tbody> <tr v-for="studio in studios" :key="studio.id"> <td> <input type="checkbox" :value="studio.id" v-model="checkedIds" > </td> <td> <span class="place" :class="{ 'top-1': studio.position === 1, 'top-2': studio.position === 2, 'top-3': studio.position === 3 }" > {{ studio.position }} </span> </td> <td> <img :src="studio.img" alt="logo" class="logo" @error="setDefaultLogo" > {{ studio.name }} </td> <td>{{ formatNumber(studio.balls) }}</td> <td>{{ studio.cases }}</td> <td>{{ formatMoney(studio.gain) }}</td> </tr> </tbody> </table> <div class="controls" v-if="page < totalPages"> <button @click="loadMore" :disabled="loadingMore"> {{ loadingMore ? 'Загрузка...' : 'Загрузить ещё' }} </button> </div> <div class="selected-box" v-if="selectedStudios.length > 0"> <strong>Выбрано компаний: {{ selectedStudios.length }}</strong> <div class="selected-list"> <div class="selected-item" v-for="studio in selectedStudios" :key="studio.id"> <img :src="studio.img" class="small-logo" @error="setDefaultLogo"> <span>{{ studio.name }}</span> <button class="delete-btn" @click="removeSelected(studio.id)">×</button> </div> </div> <div style="margin-top: 12px;"> <button @click="clearSelected">Очистить выбор</button> </div> </div> </div> <script src="https://unpkg.com/vue@3/dist/vue.global.js"></script> <script> Vue.createApp({ data() { return { studios: [], checkedIds: [], page: 1, totalPages: 1, loading: false, loadingMore: false }; }, computed: { selectedStudios() { return this.studios.filter(item => this.checkedIds.includes(item.id)); } }, methods: { async getStudios(pageNumber = 1, add = false) { if (pageNumber === 1) { this.loading = true; } else { this.loadingMore = true; } try { const response = await fetch(`https://api.bgpk.info/api/companies?page=${pageNumber}`); const result = await response.json(); if (add) { this.studios = this.studios.concat(result.data); } else { this.studios = result.data; this.checkedIds = []; } this.page = result.current_page; this.totalPages = result.last_page; } catch (error) { console.log('Ошибка загрузки:', error); } finally { this.loading = false; this.loadingMore = false; } }, loadMore() { if (this.page < this.totalPages) { this.getStudios(this.page + 1, true); } }, toggleAll(event) { if (event.target.checked) { this.checkedIds = this.studios.map(item => item.id); } else { this.checkedIds = []; } }, removeSelected(id) { this.checkedIds = this.checkedIds.filter(item => item !== id); }, clearSelected() { this.checkedIds = []; }, formatNumber(value) { return String(value).replace(/\B(?=(\d{3})+(?!\d))/g, ' '); }, formatMoney(value) { if (value >= 1000000000) { return (value / 1000000000).toFixed(1) + ' млрд ₽'; } if (value >= 1000000) { return (value / 1000000).toFixed(1) + ' млн ₽'; } return value.toLocaleString() + ' ₽'; }, setDefaultLogo(event) { event.target.src = 'https://via.placeholder.com/40?text=No'; } }, mounted() { this.getStudios(); } }).mount('#app'); </script> </body> </html>