Skip to content

Commit 616bb8c

Browse files
committed
feat: Add key metrics to the dashboard
1 parent d23ac6e commit 616bb8c

File tree

8 files changed

+87
-1
lines changed

8 files changed

+87
-1
lines changed

i18n/en_US.yaml

+2
Original file line numberDiff line numberDiff line change
@@ -1762,6 +1762,8 @@ ui:
17621762
welcome: Welcome to Admin!
17631763
site_statistics: Site statistics
17641764
questions: "Questions:"
1765+
resolved: "Resolved:"
1766+
unanswered: "Unanswered:"
17651767
answers: "Answers:"
17661768
comments: "Comments:"
17671769
votes: "Votes:"

i18n/zh_CN.yaml

+2
Original file line numberDiff line numberDiff line change
@@ -1722,6 +1722,8 @@ ui:
17221722
welcome: 欢迎来到管理后台!
17231723
site_statistics: 站点统计
17241724
questions: "问题:"
1725+
resolved: "已解决:"
1726+
unanswered: "未回复:"
17251727
answers: "回答:"
17261728
comments: "评论:"
17271729
votes: "投票:"

internal/repo/question/question_repo.go

+23
Original file line numberDiff line numberDiff line change
@@ -284,6 +284,29 @@ func (qr *questionRepo) GetQuestionCount(ctx context.Context) (count int64, err
284284
return count, nil
285285
}
286286

287+
func (qr *questionRepo) GetUnansweredQuestionCount(ctx context.Context) (count int64, err error) {
288+
session := qr.data.DB.Context(ctx)
289+
session.Where(builder.Lt{"status": entity.QuestionStatusDeleted}).
290+
And(builder.Eq{"answer_count": 0})
291+
count, err = session.Count(&entity.Question{Show: entity.QuestionShow})
292+
if err != nil {
293+
return 0, errors.InternalServer(reason.DatabaseError).WithError(err).WithStack()
294+
}
295+
return count, nil
296+
}
297+
298+
func (qr *questionRepo) GetResolvedQuestionCount(ctx context.Context) (count int64, err error) {
299+
session := qr.data.DB.Context(ctx)
300+
session.Where(builder.Lt{"status": entity.QuestionStatusDeleted}).
301+
And(builder.Neq{"answer_count": 0}).
302+
And(builder.Neq{"accepted_answer_id": 0})
303+
count, err = session.Count(&entity.Question{Show: entity.QuestionShow})
304+
if err != nil {
305+
return 0, errors.InternalServer(reason.DatabaseError).WithError(err).WithStack()
306+
}
307+
return count, nil
308+
}
309+
287310
func (qr *questionRepo) GetUserQuestionCount(ctx context.Context, userID string, show int) (count int64, err error) {
288311
session := qr.data.DB.Context(ctx)
289312
session.Where(builder.Lt{"status": entity.QuestionStatusDeleted})

internal/schema/dashboard_schema.go

+4
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,10 @@ const (
3030

3131
type DashboardInfo struct {
3232
QuestionCount int64 `json:"question_count"`
33+
ResolvedCount int64 `json:"resolved_count"`
34+
ResolvedRate string `json:"resolved_rate"`
35+
UnansweredCount int64 `json:"unanswered_count"`
36+
UnansweredRate string `json:"unanswered_rate"`
3337
AnswerCount int64 `json:"answer_count"`
3438
CommentCount int64 `json:"comment_count"`
3539
VoteCount int64 `json:"vote_count"`

internal/service/dashboard/dashboard_service.go

+28-1
Original file line numberDiff line numberDiff line change
@@ -103,7 +103,6 @@ func (ds *dashboardService) Statistical(ctx context.Context) (*schema.DashboardI
103103
dashboardInfo := ds.getFromCache(ctx)
104104
if dashboardInfo == nil {
105105
dashboardInfo = &schema.DashboardInfo{}
106-
dashboardInfo.QuestionCount = ds.questionCount(ctx)
107106
dashboardInfo.AnswerCount = ds.answerCount(ctx)
108107
dashboardInfo.CommentCount = ds.commentCount(ctx)
109108
dashboardInfo.UserCount = ds.userCount(ctx)
@@ -121,6 +120,18 @@ func (ds *dashboardService) Statistical(ctx context.Context) (*schema.DashboardI
121120
dashboardInfo.DatabaseSize = ds.GetDatabaseSize()
122121
}
123122

123+
dashboardInfo.QuestionCount = ds.questionCount(ctx)
124+
dashboardInfo.UnansweredCount = ds.unansweredQuestionCount(ctx)
125+
dashboardInfo.ResolvedCount = ds.resolvedQuestionCount(ctx)
126+
127+
if dashboardInfo.QuestionCount == 0 {
128+
dashboardInfo.ResolvedRate = "0.00"
129+
dashboardInfo.UnansweredRate = "0.00"
130+
} else {
131+
dashboardInfo.ResolvedRate = fmt.Sprintf("%.2f", float64(dashboardInfo.ResolvedCount)/float64(dashboardInfo.QuestionCount)*100)
132+
dashboardInfo.UnansweredRate = fmt.Sprintf("%.2f", float64(dashboardInfo.UnansweredCount)/float64(dashboardInfo.QuestionCount)*100)
133+
}
134+
124135
dashboardInfo.ReportCount = ds.reportCount(ctx)
125136
dashboardInfo.SMTP = ds.smtpStatus(ctx)
126137
dashboardInfo.HTTPS = ds.httpsStatus(ctx)
@@ -170,6 +181,22 @@ func (ds *dashboardService) questionCount(ctx context.Context) int64 {
170181
return questionCount
171182
}
172183

184+
func (ds *dashboardService) unansweredQuestionCount(ctx context.Context) int64 {
185+
unansweredQuestionCount, err := ds.questionRepo.GetUnansweredQuestionCount(ctx)
186+
if err != nil {
187+
log.Errorf("get unanswered question count failed: %s", err)
188+
}
189+
return unansweredQuestionCount
190+
}
191+
192+
func (ds *dashboardService) resolvedQuestionCount(ctx context.Context) int64 {
193+
resolvedQuestionCount, err := ds.questionRepo.GetResolvedQuestionCount(ctx)
194+
if err != nil {
195+
log.Errorf("get resolved question count failed: %s", err)
196+
}
197+
return resolvedQuestionCount
198+
}
199+
173200
func (ds *dashboardService) answerCount(ctx context.Context) int64 {
174201
answerCount, err := ds.answerRepo.GetAnswerCount(ctx)
175202
if err != nil {

internal/service/question_common/question.go

+2
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,8 @@ type QuestionRepo interface {
7474
FindByID(ctx context.Context, id []string) (questionList []*entity.Question, err error)
7575
AdminQuestionPage(ctx context.Context, search *schema.AdminQuestionPageReq) ([]*entity.Question, int64, error)
7676
GetQuestionCount(ctx context.Context) (count int64, err error)
77+
GetUnansweredQuestionCount(ctx context.Context) (count int64, err error)
78+
GetResolvedQuestionCount(ctx context.Context) (count int64, err error)
7779
GetUserQuestionCount(ctx context.Context, userID string, show int) (count int64, err error)
7880
SitemapQuestions(ctx context.Context, page, pageSize int) (questionIDList []*schema.SiteMapQuestionInfo, err error)
7981
RemoveAllUserQuestion(ctx context.Context, userID string) (err error)

ui/src/common/interface.ts

+4
Original file line numberDiff line numberDiff line change
@@ -524,6 +524,10 @@ export interface SearchRes extends ListResult<SearchResItem> {
524524
export interface AdminDashboard {
525525
info: {
526526
question_count: number;
527+
resolved_count: number;
528+
resolved_rate: string;
529+
unanswered_count: number;
530+
unanswered_rate: string;
527531
answer_count: number;
528532
comment_count: number;
529533
vote_count: number;

ui/src/pages/Admin/Dashboard/components/Statistics/index.tsx

+22
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,28 @@ const Statistics: FC<IProps> = ({ data }) => {
3939
<span className="text-secondary me-1">{t('questions')}</span>
4040
<strong>{data.question_count}</strong>
4141
</Col>
42+
<Col xs={6} className="mb-1">
43+
<span className="text-secondary me-1">{t('resolved')}</span>
44+
<strong>{data.resolved_count}</strong>
45+
{data.resolved_count > 0 ? (
46+
<span className="text-secondary m-1">
47+
({data.resolved_rate}%)
48+
</span>
49+
) : (
50+
''
51+
)}
52+
</Col>
53+
<Col xs={6} className="mb-1">
54+
<span className="text-secondary me-1">{t('unanswered')}</span>
55+
<strong>{data.unanswered_count}</strong>
56+
{data.unanswered_count > 0 ? (
57+
<span className="text-secondary m-1">
58+
({data.unanswered_rate}%)
59+
</span>
60+
) : (
61+
''
62+
)}
63+
</Col>
4264
<Col xs={6} className="mb-1">
4365
<span className="text-secondary me-1">{t('answers')}</span>
4466
<strong>{data.answer_count}</strong>

0 commit comments

Comments
 (0)