#javascript #vue.js #vuejs2
Вопрос:
Мое приложение vue в настоящее время выполняет итерацию по объекту данных сотрудников с указанием часов и результатов, которые умножаются для каждого сотрудника каждый день.
Это работает при вычислении новых строк данных, чтобы у меня были все данные за каждый день.
Однако в моем шаблоне я пытаюсь настроить отображение множественных данных в столбце с соответствующей датой и указать только одну строку для каждого сотрудника. Мои ожидаемые результаты были бы
Employee | 2021-08-31 | 2021-09-01 | 2021-09-02
-----------------------------------------------------
Evan 60 60
Stan 100 200
Kelly 60 164
Как я могу изменить то, что я делаю, чтобы у меня была только одна строка на сотрудника, и поместить данные в правильный столбец на основе даты заголовка столбца и даты в объекте для этой записи?
<div id="app">
<table>
<thead>
<tr>
<th>Employee</th>
<th>2021-08-31</th>
<th>2021-09-01</th>
<th>2021-09-02</th>
<th>Grand Total</th>
</tr>
</thead>
<tbody>
<tr v-for="(row, index) in compRows">
<td v-html="row.employee"></td>
<td v-if="row.workDate == {{$date->addDay()->format($format)}}"></td>
<td v-html="row.hours"></td>
</tr>
</tbody>
</table>
</div>
@endsection
@section('loadjs')
<script>
new Vue({
el: "#app",
data: {
rows: [
{
employee: "Evan",
hours: "15",
workDate: "2021-08-31",
swipes: "4",
},
{
employee: "Kelly",
hours: "15",
workDate: "2021-08-31",
swipes: "4",
},
{
employee: "Evan",
hours: "15",
workDate: "2021-09-01",
swipes: "4",
},
{
employee: "Stan",
hours: "25",
workDate: "2021-08-31",
swipes: "4",
},
{
employee: "Kelly",
hours: "82",
workDate: "2021-09-02",
swipes: "2",
},
{
employee: "Stan",
hours: "40",
workDate: "2021-09-01",
swipes: "5",
}
]
},
methods: {
},
computed: {
compRows() {
const grouped = this.rows.reduce((r, o) => {
r[o.employee] ??= {};
r[o.employee][o.workDate] ??= {employee: o.employee, workDate: o.workDate, swipes: 0, hours: 0};
r[o.employee][o.workDate].swipes = o.swipes;
r[o.employee][o.workDate].hours = o.hours;
return r;
}, {});
return Object.values(grouped).map(o => Object.values(o)).flat();
}
}
});
</script>
Ответ №1:
- Вместо того чтобы сгруппировать данные в
compRows
реквизите (переименованном ниже какhoursByEmployee
), сохраните его в качестве объекта для поиска сотрудников по часам по дате позже. Кроме того, отследите свойство, в котором хранится общая сумма (по часам).total
export default { computed: { hoursByEmployee() { return this.rows.reduce((r, o) => { r[o.employee] ??= {} r[o.employee][o.workDate] ??= {swipes: 0, hours: 0} r[o.employee][o.workDate].swipes = o.swipes r[o.employee][o.workDate].hours = o.hours r[o.employee].total ??= 0 👈 r[o.employee].total = ( o.swipes * o.hours) 👈 return r }, {}) }, } }
- Используйте другое вычисляемое свойство , чтобы получить доступные даты из строк
workDate
, отсортированных в хронологическом порядке:export default { computed: { dates() { const dates = [...new Set(this.rows.map(r => r.workDate))] return dates.sort((a,b) => new Date(a) - new Date(b)) }, } }
- В заголовке таблицы шаблона отобразите вычисленный
dates
:<thead> <tr> <th>Employee</th> <th v-for="date in dates" :key="date">{{ date }}</th> 👈 <th>Grand Total</th> </tr> </thead>
- В теле таблицы шаблона отобразите вычисленные часы работы сотрудников по дате, используя
hoursByEmployee
поиск иdates
созданный выше. Если для даты существуют часы, отобразите общее количество дней. Кроме того, отобразите свойство grandtotal
в последнем столбце.<tbody> <tr v-for="(hours, employee) in hoursByEmployee" :key="employee"> <td>{{ employee }}</td> <td v-for="date in dates" :key="date">{{ hours[date] amp;amp; hours[date].swipes * hours[date].hours }}</td> 👈 <td>{{ hours.total }}</td> 👈 </tr> </tbody>
Комментарии:
1. Это невероятно полезный и обстоятельный ответ, спасибо! Мало того, что это работает, но я сразу понял, почему шел в неправильном направлении с выравниванием. Все это время я предполагал, что мне нужно будет сгладить, но, когда я углубился в это, я понял, что мне нужен другой подход, и, похоже, это все. Еще раз спасибо!