This is an automated email from the ASF dual-hosted git repository.

linkinstar pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/incubator-answer.git

commit 98eceff5494a2114cbe0c2846785320acc14addc
Author: sy-records <[email protected]>
AuthorDate: Thu Nov 14 17:37:43 2024 +0800

    feat: Add key metrics to the dashboard
---
 i18n/en_US.yaml                                    |  2 ++
 i18n/zh_CN.yaml                                    |  2 ++
 internal/repo/question/question_repo.go            | 23 +++++++++++++++++
 internal/schema/dashboard_schema.go                |  4 +++
 internal/service/dashboard/dashboard_service.go    | 29 +++++++++++++++++++++-
 internal/service/question_common/question.go       |  2 ++
 ui/src/common/interface.ts                         |  4 +++
 .../Dashboard/components/Statistics/index.tsx      | 22 ++++++++++++++++
 8 files changed, 87 insertions(+), 1 deletion(-)

diff --git a/i18n/en_US.yaml b/i18n/en_US.yaml
index 6f3f5215..775d7456 100644
--- a/i18n/en_US.yaml
+++ b/i18n/en_US.yaml
@@ -1762,6 +1762,8 @@ ui:
       welcome: Welcome to Admin!
       site_statistics: Site statistics
       questions: "Questions:"
+      resolved: "Resolved:"
+      unanswered: "Unanswered:"
       answers: "Answers:"
       comments: "Comments:"
       votes: "Votes:"
diff --git a/i18n/zh_CN.yaml b/i18n/zh_CN.yaml
index 85581968..d0feebb9 100644
--- a/i18n/zh_CN.yaml
+++ b/i18n/zh_CN.yaml
@@ -1722,6 +1722,8 @@ ui:
       welcome: 欢迎来到管理后台!
       site_statistics: 站点统计
       questions: "问题:"
+      resolved: "已解决:"
+      unanswered: "未回复:"
       answers: "回答:"
       comments: "评论:"
       votes: "投票:"
diff --git a/internal/repo/question/question_repo.go 
b/internal/repo/question/question_repo.go
index 16b6085f..1132501e 100644
--- a/internal/repo/question/question_repo.go
+++ b/internal/repo/question/question_repo.go
@@ -284,6 +284,29 @@ func (qr *questionRepo) GetQuestionCount(ctx 
context.Context) (count int64, err
        return count, nil
 }
 
+func (qr *questionRepo) GetUnansweredQuestionCount(ctx context.Context) (count 
int64, err error) {
+       session := qr.data.DB.Context(ctx)
+       session.Where(builder.Lt{"status": entity.QuestionStatusDeleted}).
+               And(builder.Eq{"answer_count": 0})
+       count, err = session.Count(&entity.Question{Show: entity.QuestionShow})
+       if err != nil {
+               return 0, 
errors.InternalServer(reason.DatabaseError).WithError(err).WithStack()
+       }
+       return count, nil
+}
+
+func (qr *questionRepo) GetResolvedQuestionCount(ctx context.Context) (count 
int64, err error) {
+       session := qr.data.DB.Context(ctx)
+       session.Where(builder.Lt{"status": entity.QuestionStatusDeleted}).
+               And(builder.Neq{"answer_count": 0}).
+               And(builder.Neq{"accepted_answer_id": 0})
+       count, err = session.Count(&entity.Question{Show: entity.QuestionShow})
+       if err != nil {
+               return 0, 
errors.InternalServer(reason.DatabaseError).WithError(err).WithStack()
+       }
+       return count, nil
+}
+
 func (qr *questionRepo) GetUserQuestionCount(ctx context.Context, userID 
string, show int) (count int64, err error) {
        session := qr.data.DB.Context(ctx)
        session.Where(builder.Lt{"status": entity.QuestionStatusDeleted})
diff --git a/internal/schema/dashboard_schema.go 
b/internal/schema/dashboard_schema.go
index 2d780b8c..c2c7677d 100644
--- a/internal/schema/dashboard_schema.go
+++ b/internal/schema/dashboard_schema.go
@@ -30,6 +30,10 @@ const (
 
 type DashboardInfo struct {
        QuestionCount         int64                `json:"question_count"`
+       ResolvedCount         int64                `json:"resolved_count"`
+       ResolvedRate          string               `json:"resolved_rate"`
+       UnansweredCount       int64                `json:"unanswered_count"`
+       UnansweredRate        string               `json:"unanswered_rate"`
        AnswerCount           int64                `json:"answer_count"`
        CommentCount          int64                `json:"comment_count"`
        VoteCount             int64                `json:"vote_count"`
diff --git a/internal/service/dashboard/dashboard_service.go 
b/internal/service/dashboard/dashboard_service.go
index 67abc2a7..ebc9a79d 100644
--- a/internal/service/dashboard/dashboard_service.go
+++ b/internal/service/dashboard/dashboard_service.go
@@ -103,7 +103,6 @@ func (ds *dashboardService) Statistical(ctx 
context.Context) (*schema.DashboardI
        dashboardInfo := ds.getFromCache(ctx)
        if dashboardInfo == nil {
                dashboardInfo = &schema.DashboardInfo{}
-               dashboardInfo.QuestionCount = ds.questionCount(ctx)
                dashboardInfo.AnswerCount = ds.answerCount(ctx)
                dashboardInfo.CommentCount = ds.commentCount(ctx)
                dashboardInfo.UserCount = ds.userCount(ctx)
@@ -121,6 +120,18 @@ func (ds *dashboardService) Statistical(ctx 
context.Context) (*schema.DashboardI
                dashboardInfo.DatabaseSize = ds.GetDatabaseSize()
        }
 
+       dashboardInfo.QuestionCount = ds.questionCount(ctx)
+       dashboardInfo.UnansweredCount = ds.unansweredQuestionCount(ctx)
+       dashboardInfo.ResolvedCount = ds.resolvedQuestionCount(ctx)
+
+       if dashboardInfo.QuestionCount == 0 {
+               dashboardInfo.ResolvedRate = "0.00"
+               dashboardInfo.UnansweredRate = "0.00"
+       } else {
+               dashboardInfo.ResolvedRate = fmt.Sprintf("%.2f", 
float64(dashboardInfo.ResolvedCount)/float64(dashboardInfo.QuestionCount)*100)
+               dashboardInfo.UnansweredRate = fmt.Sprintf("%.2f", 
float64(dashboardInfo.UnansweredCount)/float64(dashboardInfo.QuestionCount)*100)
+       }
+
        dashboardInfo.ReportCount = ds.reportCount(ctx)
        dashboardInfo.SMTP = ds.smtpStatus(ctx)
        dashboardInfo.HTTPS = ds.httpsStatus(ctx)
@@ -170,6 +181,22 @@ func (ds *dashboardService) questionCount(ctx 
context.Context) int64 {
        return questionCount
 }
 
+func (ds *dashboardService) unansweredQuestionCount(ctx context.Context) int64 
{
+       unansweredQuestionCount, err := 
ds.questionRepo.GetUnansweredQuestionCount(ctx)
+       if err != nil {
+               log.Errorf("get unanswered question count failed: %s", err)
+       }
+       return unansweredQuestionCount
+}
+
+func (ds *dashboardService) resolvedQuestionCount(ctx context.Context) int64 {
+       resolvedQuestionCount, err := 
ds.questionRepo.GetResolvedQuestionCount(ctx)
+       if err != nil {
+               log.Errorf("get resolved question count failed: %s", err)
+       }
+       return resolvedQuestionCount
+}
+
 func (ds *dashboardService) answerCount(ctx context.Context) int64 {
        answerCount, err := ds.answerRepo.GetAnswerCount(ctx)
        if err != nil {
diff --git a/internal/service/question_common/question.go 
b/internal/service/question_common/question.go
index 13df3389..08c74f29 100644
--- a/internal/service/question_common/question.go
+++ b/internal/service/question_common/question.go
@@ -74,6 +74,8 @@ type QuestionRepo interface {
        FindByID(ctx context.Context, id []string) (questionList 
[]*entity.Question, err error)
        AdminQuestionPage(ctx context.Context, search 
*schema.AdminQuestionPageReq) ([]*entity.Question, int64, error)
        GetQuestionCount(ctx context.Context) (count int64, err error)
+       GetUnansweredQuestionCount(ctx context.Context) (count int64, err error)
+       GetResolvedQuestionCount(ctx context.Context) (count int64, err error)
        GetUserQuestionCount(ctx context.Context, userID string, show int) 
(count int64, err error)
        SitemapQuestions(ctx context.Context, page, pageSize int) 
(questionIDList []*schema.SiteMapQuestionInfo, err error)
        RemoveAllUserQuestion(ctx context.Context, userID string) (err error)
diff --git a/ui/src/common/interface.ts b/ui/src/common/interface.ts
index 8a933471..903c5c28 100644
--- a/ui/src/common/interface.ts
+++ b/ui/src/common/interface.ts
@@ -524,6 +524,10 @@ export interface SearchRes extends 
ListResult<SearchResItem> {
 export interface AdminDashboard {
   info: {
     question_count: number;
+    resolved_count: number;
+    resolved_rate: string;
+    unanswered_count: number;
+    unanswered_rate: string;
     answer_count: number;
     comment_count: number;
     vote_count: number;
diff --git a/ui/src/pages/Admin/Dashboard/components/Statistics/index.tsx 
b/ui/src/pages/Admin/Dashboard/components/Statistics/index.tsx
index c95eaba7..a3077ba4 100644
--- a/ui/src/pages/Admin/Dashboard/components/Statistics/index.tsx
+++ b/ui/src/pages/Admin/Dashboard/components/Statistics/index.tsx
@@ -39,6 +39,28 @@ const Statistics: FC<IProps> = ({ data }) => {
             <span className="text-secondary me-1">{t('questions')}</span>
             <strong>{data.question_count}</strong>
           </Col>
+          <Col xs={6} className="mb-1">
+            <span className="text-secondary me-1">{t('resolved')}</span>
+            <strong>{data.resolved_count}</strong>
+            {data.resolved_count > 0 ? (
+              <span className="text-secondary m-1">
+                ({data.resolved_rate}%)
+              </span>
+            ) : (
+              ''
+            )}
+          </Col>
+          <Col xs={6} className="mb-1">
+            <span className="text-secondary me-1">{t('unanswered')}</span>
+            <strong>{data.unanswered_count}</strong>
+            {data.unanswered_count > 0 ? (
+              <span className="text-secondary m-1">
+                ({data.unanswered_rate}%)
+              </span>
+            ) : (
+              ''
+            )}
+          </Col>
           <Col xs={6} className="mb-1">
             <span className="text-secondary me-1">{t('answers')}</span>
             <strong>{data.answer_count}</strong>

Reply via email to