44import pandas as pd
55import streamlit as st
66from dotenv import load_dotenv
7-
7+ import matplotlib . pyplot as plt
88from biz .service .review_service import ReviewService
99
1010load_dotenv ("conf/.env" )
@@ -24,7 +24,8 @@ def authenticate(username, password):
2424
2525# 获取数据函数
2626def get_data (service_func , authors = None , project_names = None , updated_at_gte = None , updated_at_lte = None , columns = None ):
27- df = service_func (authors = authors , project_names = project_names , updated_at_gte = updated_at_gte , updated_at_lte = updated_at_lte )
27+ df = service_func (authors = authors , project_names = project_names , updated_at_gte = updated_at_gte ,
28+ updated_at_lte = updated_at_lte )
2829
2930 if df .empty :
3031 return pd .DataFrame (columns = columns )
@@ -72,6 +73,104 @@ def login_page():
7273 st .error ("用户名或密码错误" )
7374
7475
76+ # 生成项目提交数量图表
77+ def generate_project_count_chart (df ):
78+ if df .empty :
79+ st .info ("没有数据可供展示" )
80+ return
81+
82+ # 计算每个项目的提交数量
83+ project_counts = df ['project_name' ].value_counts ().reset_index ()
84+ project_counts .columns = ['project_name' , 'count' ]
85+
86+ # 生成颜色列表,每个项目一个颜色
87+ colors = plt .colormaps ['tab20' ].resampled (len (project_counts ))
88+
89+ # 显示提交数量柱状图
90+ fig1 , ax1 = plt .subplots (figsize = (10 , 6 ))
91+ ax1 .bar (
92+ project_counts ['project_name' ],
93+ project_counts ['count' ],
94+ color = [colors (i ) for i in range (len (project_counts ))]
95+ )
96+ plt .xticks (rotation = 45 , ha = 'right' , fontsize = 26 )
97+ plt .tight_layout ()
98+ st .pyplot (fig1 )
99+
100+
101+ # 生成项目平均分数图表
102+ def generate_project_score_chart (df ):
103+ if df .empty :
104+ st .info ("没有数据可供展示" )
105+ return
106+
107+ # 计算每个项目的平均分数
108+ project_scores = df .groupby ('project_name' )['score' ].mean ().reset_index ()
109+ project_scores .columns = ['project_name' , 'average_score' ]
110+
111+ # 生成颜色列表,每个项目一个颜色
112+ # colors = plt.cm.get_cmap('Accent', len(project_scores)) # 使用'tab20'颜色映射,适合分类数据
113+ colors = plt .colormaps ['Accent' ].resampled (len (project_scores ))
114+ # 显示平均分数柱状图
115+ fig2 , ax2 = plt .subplots (figsize = (10 , 6 ))
116+ ax2 .bar (
117+ project_scores ['project_name' ],
118+ project_scores ['average_score' ],
119+ color = [colors (i ) for i in range (len (project_scores ))]
120+ )
121+ plt .xticks (rotation = 45 , ha = 'right' , fontsize = 26 )
122+ plt .tight_layout ()
123+ st .pyplot (fig2 )
124+
125+
126+ # 生成人员提交数量图表
127+ def generate_author_count_chart (df ):
128+ if df .empty :
129+ st .info ("没有数据可供展示" )
130+ return
131+
132+ # 计算每个人员的提交数量
133+ author_counts = df ['author' ].value_counts ().reset_index ()
134+ author_counts .columns = ['author' , 'count' ]
135+
136+ # 生成颜色列表,每个项目一个颜色
137+ colors = plt .colormaps ['Paired' ].resampled (len (author_counts ))
138+ # 显示提交数量柱状图
139+ fig1 , ax1 = plt .subplots (figsize = (10 , 6 ))
140+ ax1 .bar (
141+ author_counts ['author' ],
142+ author_counts ['count' ],
143+ color = [colors (i ) for i in range (len (author_counts ))]
144+ )
145+ plt .xticks (rotation = 45 , ha = 'right' , fontsize = 26 )
146+ plt .tight_layout ()
147+ st .pyplot (fig1 )
148+
149+
150+ # 生成人员平均分数图表
151+ def generate_author_score_chart (df ):
152+ if df .empty :
153+ st .info ("没有数据可供展示" )
154+ return
155+
156+ # 计算每个人员的平均分数
157+ author_scores = df .groupby ('author' )['score' ].mean ().reset_index ()
158+ author_scores .columns = ['author' , 'average_score' ]
159+
160+ # 显示平均分数柱状图
161+ fig2 , ax2 = plt .subplots (figsize = (10 , 6 ))
162+ # 生成颜色列表,每个项目一个颜色
163+ colors = plt .colormaps ['Pastel1' ].resampled (len (author_scores ))
164+ ax2 .bar (
165+ author_scores ['author' ],
166+ author_scores ['average_score' ],
167+ color = [colors (i ) for i in range (len (author_scores ))]
168+ )
169+ plt .xticks (rotation = 45 , ha = 'right' , fontsize = 26 )
170+ plt .tight_layout ()
171+ st .pyplot (fig2 )
172+
173+
75174# 主要内容
76175def main_page ():
77176 st .markdown ("#### 审查日志" )
@@ -109,7 +208,8 @@ def display_data(tab, service_func, columns, column_config):
109208 with col4 :
110209 project_names = st .multiselect ("项目名" , unique_projects , default = [], key = f"{ tab } _projects" )
111210
112- data = get_data (service_func , authors = authors ,project_names = project_names , updated_at_gte = int (start_datetime .timestamp ()),
211+ data = get_data (service_func , authors = authors , project_names = project_names ,
212+ updated_at_gte = int (start_datetime .timestamp ()),
113213 updated_at_lte = int (end_datetime .timestamp ()), columns = columns )
114214 df = pd .DataFrame (data )
115215
@@ -123,6 +223,21 @@ def display_data(tab, service_func, columns, column_config):
123223 average_score = df ["score" ].mean () if not df .empty else 0
124224 st .markdown (f"**总记录数:** { total_records } ,**平均分:** { average_score :.2f} " )
125225
226+ # 创建2x2网格布局展示四个图表
227+ row1 , row2 , row3 , row4 = st .columns (4 )
228+ with row1 :
229+ st .markdown ("<div style='text-align: center;'><b>项目提交次数</b></div>" , unsafe_allow_html = True )
230+ generate_project_count_chart (df )
231+ with row2 :
232+ st .markdown ("<div style='text-align: center;'><b>项目平均分数</b></div>" , unsafe_allow_html = True )
233+ generate_project_score_chart (df )
234+ with row3 :
235+ st .markdown ("<div style='text-align: center;'><b>人员提交次数</b></div>" , unsafe_allow_html = True )
236+ generate_author_count_chart (df )
237+ with row4 :
238+ st .markdown ("<div style='text-align: center;'><b>人员平均分数</b></div>" , unsafe_allow_html = True )
239+ generate_author_score_chart (df )
240+
126241 # Merge Request 数据展示
127242 mr_columns = ["project_name" , "author" , "source_branch" , "target_branch" , "updated_at" , "commit_messages" , "score" ,
128243 "url" ]
0 commit comments