Вопрос: при выборе года и месяца календарь заполняется данными о выходе сотрудника на работу по плану и факту за определенный месяц... не получается отстроить график так, чтобы отображалась данные за следующий и предыдущий месяцы...
Код:
<template>
<div class="outputGraph">
<div class="window">
<div class="window-charts">
<div class="window-charts-text">
<p>График выходов</p>
</div>
<div class="window-charts-block">
<div class="window-charts-block-btn" @click.stop="showModalYears()" ref="clickBlock">
<p ref="yearsMonth">{{ objCurrentYearsMonth.date }}</p>
<span></span>
</div>
<div class="window-charts-block-modal opacity" ref="modalCalendar">
<!-- модалка календаря -->
<div class="window-charts-block-modal-years noheader" ref="years" >
<span class="noheader previous" @click="switchYears($event)"></span>
<p class="noheader" ref="yearsActive">{{ objCurrentYearsMonth.currentYears }}</p>
<span class="noheader next" @click="switchYears($event)"></span>
</div>
<div class="window-charts-block-modal-month" v-on:click="addModalYears($event)" v-for="i in listMonth" ref="blockMonth"><span
ref="clickMonth">{{ i }}</span>
</div>
</div>
</div>
</div>
<div class="output-graph">
<div class="output-graph__days">
<div v-for="key in listDays"><span>{{ key }}</span></div>
</div>
<div class="output-graph__graphic">
<div class="output-graph__graphic__block" ref="graphicBlock"
v-for="key in objCurrentYearsMonth.startDay">
<div class="output-graph__graphic__block-transform">
<div class="block">
<span></span> <!-- строим по порядку, пока дней хватает в месяце-->
<span></span> <!-- после, начинаем новый отсчет-->
</div>
<div>
<span></span>
</div>
</div>
<div class="daysPlan">
<span class="disagree"
></span>
<span></span>
</div>
</div>
<div class="output-graph__graphic__block" v-for="key in objCurrentYearsMonth.maxDaysThisMonth">
<div class="output-graph__graphic__block-transform">
<div class="block">
<span v-if="key <= objCurrentYearsMonth.maxDaysThisMonth">{{ key }}</span>
<!-- строим по порядку, пока дней хватает в месяце-->
<span v-if="key > objCurrentYearsMonth.maxDaysThisMonth">{{ key - objCurrentYearsMonth.maxDaysThisMonth }}</span>
<!-- после, начинаем новый отсчет-->
</div>
<div>
<span title="план">{{ employeeExitSchedule.daysPlan[key - 1] }}</span>
</div>
</div>
<div class="daysPlan">
<span class="disagree"
v-if="employeeExitSchedule.daysFact[key - 1] !== employeeExitSchedule.daysPlan[key - 1]">{{ employeeExitSchedule.daysFact[key - 1] }}</span>
<span v-if="employeeExitSchedule.daysFact[key - 1] === employeeExitSchedule.daysPlan[key - 1]" title="факт">{{ employeeExitSchedule.daysFact[key - 1] }}</span>
</div>
</div>
<div class="output-graph__graphic__block" ref="graphicBlock"
v-for="key in objCurrentYearsMonth.endDay">
<div class="output-graph__graphic__block-transform">
<div class="block">
<span></span> <!-- строим по порядку, пока дней хватает в месяце-->
<span></span> <!-- после, начинаем новый отсчет-->
</div>
<div>
<span></span>
</div>
</div>
<div class="daysPlan">
<span class="disagree"
></span>
<span></span>
</div>
</div>
</div>
</div>
</div>
</div>
</template>
<script>
export default {
name: "employeeCardExitSchedule",
props: {
workerId: Number
},
data: function () {
return {
objCurrentYearsMonth: { // Объект содеражащий общую информацию
currentYears: '', // выбранный год
currentMonth: '', // выбранный месяц
NumberMonth: '', // номер выбранного месяца
date: '', // данные выводимые в текущий год и месяц
maxDaysThisMonth: '', // количество дней в текущем месяце
startDay: '', // номер дня с которого начался месяц
endDay: '', // номер дня с которого начался месяц
normalDayPlan: 0, // норма дней plan
normalHourPlan: 0, // норма часов plan
normalDayFact: 0, // норма дней fact
normalHourFact: 0, // норма часов fact
processingDay: 0, // переработка по дням
processingHour: 0, // переработка по часам
},
listDays: ['ПН', 'ВТ', 'СР', 'ЧТ', 'ПТ', 'СБ', 'ВС'], // дни недели для отображения в построении блока
listMonth: ["Январь", "Феврваль", "Март", "Апрель", "Май", "Июнь", "Июль", "Август", "Сентябрь", "Октябрь", "Ноябрь", "Декабрь"], // список месяцев
employeeExitSchedule: {}, //пришедшие данные с сервера по графику выхода сотрудника
numberWeek: '' // количество недель, которые захватывает месяц
}
},
methods: {
/**
* Функция отображения календаря по клику и сохранения данных выбранные пользователем
*/
showModalYears() {
let modalCalendar = this.$refs.modalCalendar; // если у dom элемента по refs ссылке есть селектор 'opacity', то удаляется и теи самым список отображаеться
modalCalendar.classList.toggle('opacity'); // если класса 'opacity' нет, добавляет его, если есть – удаляет.
},
/**
* Функция обрабатывает события клика во время выбора месяца из списка,
* определяет номер выбранного месяца и год
* Входные параметры: event - элемент по которому произведен клик
* На выходе записываем выбранный год и месяц, идентификатор месяца
*/
addModalYears(event) {
let year = this.$refs.yearsActive.textContent, // определяем выбранный год
numberMonth = 0; // номер выбранного месяца
this.showModalYears(); // вызов метода showModalYears()
//console.log(this.objCurrentYearsMonth.date);
for (let i = 0; i < this.listMonth.length; i++) { // цикл по перебору массива месяцев и нахождение месяца по счету который выбрали
if (this.listMonth[i] === event.target.textContent) { // если этот месяц равен событию на которое кликаем
numberMonth = i; // то выбирается
break
}
}
this.clickDate(new Date(year, numberMonth)) // вызов метода для получения данных за месяц
},
/**
* Метод при первоначальной загрузке страницы определяет текущую дату и вызывает метод
* (если агрумент не был передан по умолчанию устанавливается текущая дата)
* на ajax-запрос по получению данных за месяц.
*/
clickDate(selectedDate = new Date()) {
this.ajaxDataMonth(selectedDate); // При выборе другого месяца или/и года, в функцию передается дата с выбранным годом и месяцем
let year = selectedDate.getFullYear(), // вычисляем текущий год
month = selectedDate.getMonth(), // вычисляем текущий месяц
cuntDay = new Date(year, month + 1, 0).getDate(), // количество дней в текущем месяце
startDay = new Date(year, month).getDay(), // день недели начала месяца
endDay = new Date(year, month + 1, 0).getDay(); // день недели окончания месяца
if (startDay === 0) { // устанавливаем значение для достройки в начале пустых ячеек календаря(если равно 0)
this.objCurrentYearsMonth.startDay = 6; // то значение дня с которого начинался месяц равно 6часам
} else { // иначе
this.objCurrentYearsMonth.startDay = startDay - 1; // отнимаем 1 смену
}
if (endDay === 0) { // устанавливаем значение для достройки в конце пустых ячеек календаря(если равно 0)
this.objCurrentYearsMonth.endDay = endDay; // то это последний день
} else { // иначе
this.objCurrentYearsMonth.endDay = 7 - endDay; // отнимаем
}
this.objCurrentYearsMonth.currentYears = year; // записал год нынешний
this.objCurrentYearsMonth.maxDaysThisMonth = cuntDay; // записал количество дней в текущем месяце
this.objCurrentYearsMonth.NumberMonth = month;
this.objCurrentYearsMonth.date = this.listMonth[month] + " " + year; //записал строку месяц и год
let dateWeek = new Date(year, month + 1, 0);
this.numberWeek = Math.ceil( (dateWeek.getDate() - (dateWeek.getDay() ? dateWeek.getDay() : 7) ) / 7 ) +1;
for (let i = 0; i < this.$refs.blockMonth.length; i++) {
if (this.$refs.blockMonth[i].classList.contains('month-active')) {
this.$refs.blockMonth[i].classList.remove('month-active');
break
}
}
this.$refs.blockMonth[this.objCurrentYearsMonth.NumberMonth].classList.add('month-active');
console.log('Год - ', this.objCurrentYearsMonth.currentYears, 'Номер месяца - ', this.objCurrentYearsMonth.NumberMonth);
},
/**
* Метод ajax-запроса на получение данных по графику работ за выбранные месяц
*/
ajaxDataMonth(selectedDate) { // selectedDate-выбранная дата
this.employeeExitSchedule = { // Тестовый набор входных данных и результатов их обработки
daysFact: ['1', '1', '1', 'в', '2', 'в', '1', '1', '1', 'в', 'в', '2', '1', 'в', '1', '1', '1', 'в', '1', '2', '1', '1', 'в', 'в', 'в', '1', '1', '1', 'в', '1', '1'], // фактический график выходов
daysPlan: ['в', '2', '1', '1', 'в', 'в', '1', '1', '1', 'в', 'в', '1', '1', 'в', '1', '1', '2', 'в', '1', '1', '1', '1', '1', 'в', 'в', '1', '1', '1', 'в', '1', '2'] // плановый график выходов
};
this.calculationDay(this.employeeExitSchedule, this.objCurrentYearsMonth)
},
/**
* функция по выбору года
* входные параметры
* event - элемент по которому кликнули
* */
switchYears(event) {
if (event.target.classList.contains('next')) { // если dom элемент "кнопка вперед"
this.objCurrentYearsMonth.currentYears = +this.objCurrentYearsMonth.currentYears + 1; // тогда добавляем год на 1
} else if (event.target.classList.contains('previous')) { // если dom элемент кнопка "назад"
this.objCurrentYearsMonth.currentYears = +this.objCurrentYearsMonth.currentYears - 1; // тогда отнимаем год на 1
}
},
/*
Запрос на получение данных о графике выходов
*/
async getGraphicWorkerCard(workerObjId) {
const postData = {
controller: 'ordersystem\\WorkSchedule', // путь контроллеру
method: 'GetGraphicWorkerCard', // имя метода для полученния данных работника
subscribe: '', // подписка на список работникаов
data: JSON.stringify({
worker_id: workerObjId,
month: '',
year: ''
})
};
let workerGraphic = await sendAjax(postData);
this.employeeExitSchedule = workerGraphic.Items;
},
},
computed: {
monthlyWorkerGraphic() {
return this.workerGraphic;
}
},
mounted() {
this.clickDate();
}
}
</script>
Пример реализации календаря, точнее шаблон. Разбито на компоненты: месяц, неделя, день. Данные уже прокините сами
const Day = Vue.component('Day', {
props: ['date'],
template: `<div class='day'>{{date.getDate()}}</div>`,
});
const Week = Vue.component('Week', {
props: ['weekIndex', 'dayOfWeek'],
components: { Day },
template: `<div class='week'>
<Day
v-for="index in 7"
:date="getDate(index)"
:key="getDate(index).getTime()">
</Day>
</div>`,
computed: {
startDay() {
// определяем день года, с которого необходимо начать отрисовку недели
const dayIndex = this.dayOfWeek.getDay() || 7;
const different = time.day * (dayIndex - 1);
const start = this.dayOfWeek - different;
return new Date(start);
},
},
methods: {
getDate(index) {
return new Date(this.startDay.getTime() + time.day * (index - 1));
},
},
});
const time = {
day: 1000 * 60 * 60 * 24,
week: 1000 * 60 * 60 * 24 * 7,
};
const Month = Vue.component('Month', {
props: ['date'],
components: { Week },
template: `<div>
<div>{{monthName}}</div>
<div class='month'>
<Week
v-for="index in 6"
:key="index"
:weekIndex="index"
:dayOfWeek='getDayOfWeek(index)'>
</Week>
</div>
</div>`,
computed: {
monthName() {
return this.date.toLocaleDateString('en-US', { month: 'short' });
},
startDay() {
if (!this.date) return;
// 1-й день месяца
return new Date(this.date.getFullYear(), this.date.getMonth());
},
},
methods: {
getDayOfWeek(index) {
// по сути, просто какой-нибудь день той недели, в которою мы передаем данные
return new Date(this.startDay.getTime() + time.week * (index - 1));
},
},
});
new Vue({
el: '#app',
components: { Month },
template: `<div><input v-model="value" type='date'>
<Month v-if="date" :date="date"></Month>
</div>`,
data() {
return {
value: new Date(),
};
},
computed: {
date() {
const z = new Date(this.value);
return z.toString() === 'Invalid Date' ? false : z;
},
},
});
body{
background-color: white;
overflow: hidden;
}
#app{
height: 100vh;
border: 1px solid red;
overflow: scroll;
}
.month{
width: 300px;
border: 1px solid red
}
.week{
display: flex;
}
.day{
width: 13%;
height: 30px;
flex-grow: 3;
border: 1px solid;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.6.1/vue.js"></script>
<div id="app"> </div>
Айфон мало держит заряд, разбираемся с проблемой вместе с AppLab
Перевод документов на английский язык: Важность и ключевые аспекты
Вроде не новичок в JS, но вопрос возник довольно легкий и глупыйКак остановить по клику на кнопку интервальное выполнение функции, а затем...
Подскажите, пожалуйста, как правильно лениво загружать (желательно по скроллу) картинки, которые собираются через тег <picture>?
На сайте имеется блок < div id='recentpostsae' > с последними публикациямиВ нем нужно изменить src img, с 's72-c' на 's150-c', в данный момент src имеет вид https://site