From b62da90c8bfe363ca3a9783e44e79b2f8dc412b8 Mon Sep 17 00:00:00 2001 From: seaislee1209 Date: Tue, 3 Mar 2026 19:46:14 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E6=9C=AC=E6=9C=88=E4=BA=BA=E5=8A=9B?= =?UTF-8?q?=E6=88=90=E6=9C=AC=E5=8C=85=E5=90=AB=E7=AE=A1=E7=90=86=E5=B1=82?= =?UTF-8?q?=20+=20=E4=BB=8A=E6=97=A5=E6=8F=90=E4=BA=A4=E5=88=86=E7=BB=84?= =?UTF-8?q?=20+=20=E7=AD=9B=E9=80=89bug=E4=BF=AE=E5=A4=8D?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 本月人力成本 = 提交人成本 + 管理层成本(豁免角色) - 今日提交情况分三组:已提交合格(≥8h)、时间不足(<8h)、未提交 - 修复内容提交页同时筛选人和项目时筛选失效的bug Co-Authored-By: Claude Sonnet 4.5 --- backend/routers/dashboard.py | 37 +++++++++++++++++++++++++++----- backend/routers/submissions.py | 9 ++++---- frontend/src/views/Dashboard.vue | 20 ++++++++++++----- 3 files changed, 51 insertions(+), 15 deletions(-) diff --git a/backend/routers/dashboard.py b/backend/routers/dashboard.py index f0e39f2..6a44921 100644 --- a/backend/routers/dashboard.py +++ b/backend/routers/dashboard.py @@ -34,7 +34,8 @@ def get_dashboard( today = date.today() month_start = today.replace(day=1) - # 本月人力成本(简化:统计本月所有有提交的人的日成本) + # 本月人力成本 = 提交人成本 + 管理层成本 + # 1. 提交人成本(统计本月所有有提交的人的日成本) monthly_submitters = db.query(Submission.user_id, Submission.submit_date).filter( Submission.submit_date >= month_start, Submission.submit_date <= today, @@ -50,6 +51,26 @@ def get_dashboard( if user: monthly_labor += user.daily_cost + # 2. 管理层成本(豁免提交角色的人) + from models import Role + exempt_role_ids = set( + r.id for r in db.query(Role).filter(Role.exempt_submission == 1).all() + ) + if exempt_role_ids: + exempt_users = db.query(User).filter( + User.is_active == 1, + User.monthly_salary > 0, + User.role_id.in_(exempt_role_ids), + ).all() + # 本月有提交记录的工作日数 + monthly_working_days = db.query(Submission.submit_date).filter( + Submission.submit_date >= month_start, + Submission.submit_date <= today, + ).distinct().count() + # 管理层成本 = 每人日薪 × 本月工作日数 + monthly_management = sum(u.daily_cost * monthly_working_days for u in exempt_users) + monthly_labor += monthly_management + # 本月 AI 工具成本 monthly_ai = db.query(sa_func.sum(AIToolCost.amount)).filter( AIToolCost.record_date >= month_start, @@ -237,7 +258,8 @@ def get_dashboard( Submission.submit_date == today, ).distinct().all() ) - submitted_users = [] + submitted_sufficient = [] # 提交且满8小时 + submitted_insufficient = [] # 提交但不足8小时 not_submitted_users = [] for u in all_active_users: info = {"id": u.id, "name": u.name} @@ -247,14 +269,19 @@ def get_dashboard( Submission.submit_date == today, ).scalar() or 0 info["hours"] = round(hours, 1) - submitted_users.append(info) + if hours >= 8: + submitted_sufficient.append(info) + else: + submitted_insufficient.append(info) else: not_submitted_users.append(info) daily_attendance = { "total": len(all_active_users), - "submitted_count": len(submitted_users), + "submitted_sufficient_count": len(submitted_sufficient), + "submitted_insufficient_count": len(submitted_insufficient), "not_submitted_count": len(not_submitted_users), - "submitted": submitted_users, + "submitted_sufficient": submitted_sufficient, + "submitted_insufficient": submitted_insufficient, "not_submitted": not_submitted_users, } diff --git a/backend/routers/submissions.py b/backend/routers/submissions.py index 74d24dc..638e6de 100644 --- a/backend/routers/submissions.py +++ b/backend/routers/submissions.py @@ -48,14 +48,13 @@ def list_submissions( current_user: User = Depends(get_current_user) ): q = db.query(Submission) - # 查看项目内提交时,所有人都可见(方便横向对比) - # 全局提交列表时,没有 user:view 权限只能看自己的 - if project_id: - pass # 项目内提交不做用户过滤 - elif not current_user.has_permission("user:view"): + # 权限检查:没有 user:view 权限只能看自己的 + if not current_user.has_permission("user:view"): q = q.filter(Submission.user_id == current_user.id) elif user_id: + # 有权限且指定了用户,过滤该用户 q = q.filter(Submission.user_id == user_id) + # 项目筛选 if project_id: q = q.filter(Submission.project_id == project_id) if start_date: diff --git a/frontend/src/views/Dashboard.vue b/frontend/src/views/Dashboard.vue index d068d1f..74fe09b 100644 --- a/frontend/src/views/Dashboard.vue +++ b/frontend/src/views/Dashboard.vue @@ -74,22 +74,29 @@ 今日提交情况
- + + 时间不足 {{ data.daily_attendance.submitted_insufficient_count }}
- +
-
-
已提交({{ data.daily_attendance.submitted.length }}人)
+
+
⚠️ 时间不足({{ data.daily_attendance.submitted_insufficient.length }}人)
- + {{ u.name }} {{ u.hours }}h +
+
+
+
✅ 已提交合格({{ data.daily_attendance.submitted_sufficient.length }}人)
+
+
@@ -491,17 +498,20 @@ onUnmounted(() => { .attendance-summary { display: flex; align-items: center; gap: 8px; } .att-tag { font-size: 13px; font-weight: 600; padding: 2px 10px; border-radius: 10px; } .att-tag.submitted { color: #34C759; background: #E8F8EE; } +.att-tag.insufficient { color: #FF9500; background: #FFF3E0; } .att-tag.not-submitted { color: #FF3B30; background: #FFE8E7; } .attendance-body { padding-top: 8px !important; padding-bottom: 12px !important; } .att-section { margin-bottom: 12px; } .att-section:last-child { margin-bottom: 0; } .att-section-title { font-size: 12px; color: var(--text-secondary); margin-bottom: 8px; font-weight: 500; } .att-section-title.not-submitted-title { color: #FF3B30; } +.att-section-title.insufficient-title { color: #FF9500; } .att-user-list { display: flex; flex-wrap: wrap; gap: 6px; } .att-user { font-size: 13px; padding: 4px 12px; border-radius: 6px; white-space: nowrap; } .att-user.not-submitted { background: #FFF5F5; color: #CC2D25; font-weight: 500; } +.att-user.insufficient { background: #FFF3E0; color: #D97706; font-weight: 500; } .att-user.submitted { background: #F7F8FA; color: var(--text-regular); } .att-user.submitted small { color: var(--text-secondary); margin-left: 2px; }