From 62d36dca17b12a88eb721389691bedaed99417e4 Mon Sep 17 00:00:00 2001 From: poignatov Date: Wed, 4 Feb 2026 17:42:58 +0300 Subject: [PATCH] =?UTF-8?q?4.16.3:=20=D0=94=D0=BE=D0=B1=D0=B0=D0=B2=D0=BB?= =?UTF-8?q?=D0=B5=D0=BD=20normalized=5Ftotal=5Fscore=20=D0=B2=20=D0=BF?= =?UTF-8?q?=D1=80=D0=BE=D0=B3=D1=80=D0=B5=D1=81=D1=81=20=D0=BD=D0=B5=D0=B4?= =?UTF-8?q?=D0=B5=D0=BB=D1=8C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- VERSION | 2 +- play-life-backend/main.go | 42 ++++-- play-life-web/package.json | 2 +- .../src/components/WeekProgressChart.jsx | 132 +++++++++++------- 4 files changed, 113 insertions(+), 65 deletions(-) diff --git a/VERSION b/VERSION index 469f283..595ad53 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -4.16.2 +4.16.3 diff --git a/play-life-backend/main.go b/play-life-backend/main.go index 38f69d1..7566813 100644 --- a/play-life-backend/main.go +++ b/play-life-backend/main.go @@ -210,13 +210,14 @@ type ProjectPriorityRequest struct { } type FullStatisticsItem struct { - ProjectName string `json:"project_name"` - ReportYear int `json:"report_year"` - ReportWeek int `json:"report_week"` - TotalScore float64 `json:"total_score"` - MinGoalScore float64 `json:"min_goal_score"` - MaxGoalScore float64 `json:"max_goal_score"` - Color string `json:"color"` + ProjectName string `json:"project_name"` + ReportYear int `json:"report_year"` + ReportWeek int `json:"report_week"` + TotalScore float64 `json:"total_score"` + MinGoalScore float64 `json:"min_goal_score"` + MaxGoalScore float64 `json:"max_goal_score"` + NormalizedTotalScore float64 `json:"normalized_total_score"` + Color string `json:"color"` } type TodayEntryNode struct { @@ -6306,6 +6307,9 @@ func (a *App) getFullStatisticsHandler(w http.ResponseWriter, r *http.Request) { -- Фактический score: COALESCE(NULL, 0.0000) COALESCE(wr.total_score, 0.0000) AS total_score, + -- Normalized score из MV + COALESCE(wr.normalized_total_score, 0.0000) AS normalized_total_score, + -- Минимальная цель: COALESCE(NULL, 0.0000) COALESCE(wg.min_goal_score, 0.0000) AS min_goal_score, @@ -6353,6 +6357,7 @@ func (a *App) getFullStatisticsHandler(w http.ResponseWriter, r *http.Request) { &item.ReportYear, &item.ReportWeek, &item.TotalScore, + &item.NormalizedTotalScore, &item.MinGoalScore, &item.MaxGoalScore, &projectID, @@ -6368,9 +6373,16 @@ func (a *App) getFullStatisticsHandler(w http.ResponseWriter, r *http.Request) { if item.ReportYear == currentYearInt && item.ReportWeek == currentWeekInt { if score, exists := currentWeekScores[projectID]; exists { item.TotalScore = score + // Для текущей недели normalized_total_score не отправляем + item.NormalizedTotalScore = 0 } } + // Если normalized_total_score равен total_score, не отправляем его + if item.NormalizedTotalScore == item.TotalScore { + item.NormalizedTotalScore = 0 + } + statistics = append(statistics, item) } @@ -6423,15 +6435,17 @@ func (a *App) getFullStatisticsHandler(w http.ResponseWriter, r *http.Request) { totalScore = score } + // Для текущей недели normalized_total_score не отправляем _, weekISO := time.Now().ISOWeek() item := FullStatisticsItem{ - ProjectName: projectName, - ReportYear: time.Now().Year(), - ReportWeek: weekISO, - TotalScore: totalScore, - MinGoalScore: minGoalScore, - MaxGoalScore: maxGoalScore, - Color: projectColor, + ProjectName: projectName, + ReportYear: time.Now().Year(), + ReportWeek: weekISO, + TotalScore: totalScore, + NormalizedTotalScore: 0, + MinGoalScore: minGoalScore, + MaxGoalScore: maxGoalScore, + Color: projectColor, } statistics = append(statistics, item) } diff --git a/play-life-web/package.json b/play-life-web/package.json index 5c6020f..023fa8f 100644 --- a/play-life-web/package.json +++ b/play-life-web/package.json @@ -1,6 +1,6 @@ { "name": "play-life-web", - "version": "4.16.2", + "version": "4.16.3", "type": "module", "scripts": { "dev": "vite", diff --git a/play-life-web/src/components/WeekProgressChart.jsx b/play-life-web/src/components/WeekProgressChart.jsx index b9c8264..21f0382 100644 --- a/play-life-web/src/components/WeekProgressChart.jsx +++ b/play-life-web/src/components/WeekProgressChart.jsx @@ -81,7 +81,10 @@ function WeekProgressChart({ data, allProjectsSorted, currentWeekData, selectedP weeksMap[weekKey].push({ projectName: item.project_name, - score: parseFloat(item.total_score) || 0 + score: parseFloat(item.total_score) || 0, + minGoalScore: parseFloat(item.min_goal_score) || 0, + maxGoalScore: parseFloat(item.max_goal_score) || 0, + normalizedTotalScore: parseFloat(item.normalized_total_score) || 0 }) }) } @@ -94,7 +97,8 @@ function WeekProgressChart({ data, allProjectsSorted, currentWeekData, selectedP weeksMap[currentWeekKey] = projects.map(project => ({ projectName: project.project_name || project.name, - score: parseFloat(project.total_score || project.score || 0) + score: parseFloat(project.total_score || project.score || 0), + normalizedTotalScore: parseFloat(project.normalized_total_score) || 0 })).filter(p => { // Фильтруем по выбранному проекту, если он указан if (selectedProject && p.projectName !== selectedProject) { @@ -147,6 +151,7 @@ function WeekProgressChart({ data, allProjectsSorted, currentWeekData, selectedP // Функция для обработки данных недели const processWeekData = (weekKey) => { + const { year, week } = parseWeekKey(weekKey) const weekProjects = weeksMap[weekKey] || [] const totalScore = weekProjects.reduce((sum, p) => sum + p.score, 0) @@ -154,15 +159,20 @@ function WeekProgressChart({ data, allProjectsSorted, currentWeekData, selectedP // Сортируем проекты так же, как в полной статистике (по priority и min_goal_score) // Получаем цвет проекта из данных full-statistics, если доступен const projectsWithData = weekProjects.map(project => { - // Ищем цвет проекта в данных full-statistics - const projectData = data?.find(item => item.project_name === project.projectName) + // Ищем данные проекта в full-statistics для получения цвета и calculated_score + const projectData = data?.find(item => + item.project_name === project.projectName && + item.report_year === year && + item.report_week === week + ) const projectColor = projectData?.color ? getProjectColor(project.projectName, allProjects, projectData.color) : getProjectColor(project.projectName, allProjects) return { ...project, - color: projectColor + color: projectColor, + normalizedTotalScore: projectData?.normalized_total_score !== undefined ? parseFloat(projectData.normalized_total_score) || 0 : project.normalizedTotalScore || 0 } }) @@ -176,8 +186,6 @@ function WeekProgressChart({ data, allProjectsSorted, currentWeekData, selectedP const sortedProjectsWithData = sortedProjectNames.map(name => { return projectsWithData.find(p => p.projectName === name) }).filter(Boolean) - - const { year, week } = parseWeekKey(weekKey) return { weekKey, @@ -212,49 +220,75 @@ function WeekProgressChart({ data, allProjectsSorted, currentWeekData, selectedP } // Компонент для отображения прогрессбара недели - const WeekProgressBar = ({ weekData }) => ( -
-
- Неделя {weekData.week} + const WeekProgressBar = ({ weekData }) => { + // Находим выбранный проект в данных недели для отображения normalized значения + const selectedProjectData = selectedProject + ? weekData.projects.find(p => p.projectName === selectedProject) + : null + + return ( +
+
+ Неделя {weekData.week} +
+
+ {weekData.totalScore === 0 ? ( +
+ Нет данных +
+ ) : ( + <> + {weekData.projects.map((project, index) => { + // Вычисляем позицию и ширину для каждого сегмента на основе абсолютных значений + let left = 0 + for (let i = 0; i < index; i++) { + left += weekData.projects[i].score + } + + const widthPercent = (project.score / maxTotalScore) * 100 + const leftPercent = (left / maxTotalScore) * 100 + + return ( +
+ ) + })} + + )} +
+
+ {weekData.totalScore > 0 ? ( + <> + {selectedProjectData && + selectedProjectData.normalizedTotalScore !== undefined && + selectedProjectData.normalizedTotalScore !== null && + selectedProjectData.normalizedTotalScore > 0 && + Math.abs(selectedProjectData.normalizedTotalScore - selectedProjectData.score) > 0.01 ? ( + <> + + ({selectedProjectData.normalizedTotalScore.toFixed(1)}) + + + {selectedProjectData.score.toFixed(1)} + + + ) : ( + weekData.totalScore.toFixed(1) + )} + + ) : '-'} +
-
- {weekData.totalScore === 0 ? ( -
- Нет данных -
- ) : ( - <> - {weekData.projects.map((project, index) => { - // Вычисляем позицию и ширину для каждого сегмента на основе абсолютных значений - let left = 0 - for (let i = 0; i < index; i++) { - left += weekData.projects[i].score - } - - const widthPercent = (project.score / maxTotalScore) * 100 - const leftPercent = (left / maxTotalScore) * 100 - - return ( -
- ) - })} - - )} -
-
- {weekData.totalScore > 0 ? `${weekData.totalScore.toFixed(1)}` : '-'} -
-
- ) + ) + } return (