отображение сетки активности

This commit is contained in:
Андрей Дувакин 2025-05-31 19:10:49 +05:00
parent 24ce580bd2
commit 00d17363f2

View File

@ -80,7 +80,7 @@
<div class="activity-grid-row row no-wrap">
<!-- Дни недели слева -->
<div class="weekdays-column column q-pr-sm" style="width: 40px; user-select: none;">
<div class="weekdays-column column q-pr-sm" style="width: 40px; user-select: none; justify-content: space-around;">
<div
v-for="(day, idx) in weekDays"
:key="day"
@ -198,8 +198,15 @@ const weekDays = ['пн', 'ср', 'пт'];
const activityGrid = computed(() => {
const weeks = [];
let week = [];
let firstDay = new Date(activityData.value[0]?.date || new Date());
firstDay.setDate(firstDay.getDate() - 364); // Начинаем с 365 дней назад
const firstDay = new Date();
firstDay.setDate(firstDay.getDate() - 364); // Год назад от текущей даты
const dayOfWeek = firstDay.getDay();
const offset = dayOfWeek === 0 ? 6 : dayOfWeek - 1; // Смещение для выравнивания по понедельнику
// Добавляем пустые ячейки в начало
for (let i = 0; i < offset; i++) {
week.push({ date: '', count: 0 });
}
for (let i = 0; i < 365; i++) {
const date = new Date(firstDay);
@ -218,11 +225,11 @@ const activityGrid = computed(() => {
// Цвета активности (как в Gitea)
function getActivityColor(count) {
if (count === 0) return '#ebedf0';
if (count <= 2) return '#c6e48b';
if (count <= 4) return '#7bc96f';
if (count <= 6) return '#239a3b';
return '#196127';
if (count === 0) return '#ede9fe'; // Светлый фон карточек
if (count <= 2) return '#d8cff9'; // Светлый сиреневый
if (count <= 4) return '#a287ff'; // Светлый фиолетовый
if (count <= 6) return '#7c3aed'; // Яркий фиолетовый
return '#4f046f'; // Темно-фиолетовый
}
// Позиционирование подписей месяцев
@ -239,24 +246,23 @@ const username = 'andrei';
async function loadActivity() {
try {
const response = await axios.get(`${CONFIG.BASE_URL}/rss/${username}/`);
activityData.value = response.data;
// Дополняем до 365 дней
const fetchedData = response.data.map(item => ({
date: item.date,
count: parseInt(item.count, 10) || 0
}));
const dataMap = new Map(fetchedData.map(d => [d.date, d.count]));
const lastDate = new Date();
const startDate = new Date(lastDate);
startDate.setDate(lastDate.getDate() - 364);
const existingDates = new Set(activityData.value.map(d => d.date));
activityData.value = [];
for (let i = 0; i < 365; i++) {
const date = new Date(startDate);
date.setDate(startDate.getDate() + i);
const dateStr = date.toISOString().slice(0, 10);
const dayData = response.data.find(d => d.date === dateStr) || { date: dateStr, count: 0 };
activityData.value.push(dayData);
const count = dataMap.get(dateStr) || 0;
activityData.value.push({date: dateStr, count});
}
// Сортировка не требуется, так как мы формируем массив в правильном порядке
} catch (error) {
console.error('Ошибка загрузки активности:', error);
Notify.create({
@ -294,6 +300,18 @@ function decreaseScale() {
</script>
<style scoped>
.activity-grid {
display: flex;
flex-direction: row;
overflow-x: auto;
}
.activity-card {
max-width: 100%;
overflow-x: auto;
}
.activity-card .activity-square {
border-radius: 4px !important;
}
.bg-violet-strong {
background: linear-gradient(135deg, #4f046f 0%, #7c3aed 100%);
min-height: 100vh;
@ -301,7 +319,6 @@ function decreaseScale() {
color: #3e2465;
overflow-x: hidden;
}
.team-logo {
background: #fff;
border-radius: 50%;
@ -316,27 +333,23 @@ function decreaseScale() {
transform: scale(1.1);
box-shadow: 0 0 14px #a287ffaa;
}
.team-name-card {
border-radius: 20px;
background: #ede9fe;
box-shadow: 0 8px 24px rgba(124, 58, 237, 0.18), 0 2px 8px rgba(124, 58, 237, 0.12);
max-width: 900px;
}
.violet-card {
border-radius: 22px;
background: #ede9fe;
box-shadow: 0 8px 24px rgba(124, 58, 237, 0.18), 0 2px 8px rgba(124, 58, 237, 0.12);
transition: box-shadow 0.3s ease, transform 0.3s ease;
}
.violet-card:hover {
box-shadow: 0 14px 40px rgba(124, 58, 237, 0.30), 0 6px 16px rgba(124, 58, 237, 0.20);
transform: translateY(-6px);
cursor: pointer;
}
.member-card, .contest-card {
min-height: 140px;
padding: 8px 12px;
@ -344,27 +357,38 @@ function decreaseScale() {
flex-direction: column;
justify-content: center;
}
.activity-card {
max-width: 920px;
border-radius: 20px;
padding: 16px;
}
.activity-grid {
display: flex;
flex-direction: row;
}
.activity-week {
display: flex;
flex-direction: column;
}
.activity-square {
border-radius: 4px;
box-shadow: 0 0 3px rgba(124, 58, 237, 0.3);
cursor: default;
transition: background-color 0.3s ease;
}
.months-row {
display: flex;
flex-direction: row;
justify-content: flex-start;
margin-left: 40px; /* Синхронизация с .weekdays-column */
margin-bottom: 24px !important;
position: relative;
}
.month-label {
width: auto;
text-align: left;
white-space: nowrap;
flex-shrink: 0;
position: absolute; /* Для точного позиционирования */
}
</style>