mirror of https://gitee.com/answerdev/answer.git
Merge branch 'ai_0.3_dashboard' into test
This commit is contained in:
commit
79ba518810
|
@ -152,7 +152,7 @@ func initApplication(debug bool, serverConf *conf.Server, dbConf *data.Database,
|
|||
questionService := service.NewQuestionService(questionRepo, tagCommonService, questionCommon, userCommon, revisionService, metaService, collectionCommon, answerActivityService)
|
||||
questionController := controller.NewQuestionController(questionService, rankService)
|
||||
answerService := service.NewAnswerService(answerRepo, questionRepo, questionCommon, userCommon, collectionCommon, userRepo, revisionService, answerActivityService, answerCommon, voteRepo)
|
||||
dashboardService := dashboard.NewDashboardService(questionRepo, answerRepo, commentCommonRepo, voteRepo, userRepo, reportRepo, configRepo, siteInfoCommonService)
|
||||
dashboardService := dashboard.NewDashboardService(questionRepo, answerRepo, commentCommonRepo, voteRepo, userRepo, reportRepo, configRepo, siteInfoCommonService, serviceConf, dataData)
|
||||
answerController := controller.NewAnswerController(answerService, rankService, dashboardService)
|
||||
searchRepo := search_common.NewSearchRepo(dataData, uniqueIDRepo, userCommon)
|
||||
searchService := service.NewSearchService(searchRepo, tagRepo, userCommon, followRepo)
|
||||
|
|
24
docs/docs.go
24
docs/docs.go
|
@ -5292,11 +5292,17 @@ const docTemplate = `{
|
|||
"schema.SiteGeneralReq": {
|
||||
"type": "object",
|
||||
"required": [
|
||||
"contact_email",
|
||||
"description",
|
||||
"name",
|
||||
"short_description"
|
||||
"short_description",
|
||||
"site_url"
|
||||
],
|
||||
"properties": {
|
||||
"contact_email": {
|
||||
"type": "string",
|
||||
"maxLength": 512
|
||||
},
|
||||
"description": {
|
||||
"type": "string",
|
||||
"maxLength": 2000
|
||||
|
@ -5308,17 +5314,27 @@ const docTemplate = `{
|
|||
"short_description": {
|
||||
"type": "string",
|
||||
"maxLength": 255
|
||||
},
|
||||
"site_url": {
|
||||
"type": "string",
|
||||
"maxLength": 512
|
||||
}
|
||||
}
|
||||
},
|
||||
"schema.SiteGeneralResp": {
|
||||
"type": "object",
|
||||
"required": [
|
||||
"contact_email",
|
||||
"description",
|
||||
"name",
|
||||
"short_description"
|
||||
"short_description",
|
||||
"site_url"
|
||||
],
|
||||
"properties": {
|
||||
"contact_email": {
|
||||
"type": "string",
|
||||
"maxLength": 512
|
||||
},
|
||||
"description": {
|
||||
"type": "string",
|
||||
"maxLength": 2000
|
||||
|
@ -5330,6 +5346,10 @@ const docTemplate = `{
|
|||
"short_description": {
|
||||
"type": "string",
|
||||
"maxLength": 255
|
||||
},
|
||||
"site_url": {
|
||||
"type": "string",
|
||||
"maxLength": 512
|
||||
}
|
||||
}
|
||||
},
|
||||
|
|
|
@ -5280,11 +5280,17 @@
|
|||
"schema.SiteGeneralReq": {
|
||||
"type": "object",
|
||||
"required": [
|
||||
"contact_email",
|
||||
"description",
|
||||
"name",
|
||||
"short_description"
|
||||
"short_description",
|
||||
"site_url"
|
||||
],
|
||||
"properties": {
|
||||
"contact_email": {
|
||||
"type": "string",
|
||||
"maxLength": 512
|
||||
},
|
||||
"description": {
|
||||
"type": "string",
|
||||
"maxLength": 2000
|
||||
|
@ -5296,17 +5302,27 @@
|
|||
"short_description": {
|
||||
"type": "string",
|
||||
"maxLength": 255
|
||||
},
|
||||
"site_url": {
|
||||
"type": "string",
|
||||
"maxLength": 512
|
||||
}
|
||||
}
|
||||
},
|
||||
"schema.SiteGeneralResp": {
|
||||
"type": "object",
|
||||
"required": [
|
||||
"contact_email",
|
||||
"description",
|
||||
"name",
|
||||
"short_description"
|
||||
"short_description",
|
||||
"site_url"
|
||||
],
|
||||
"properties": {
|
||||
"contact_email": {
|
||||
"type": "string",
|
||||
"maxLength": 512
|
||||
},
|
||||
"description": {
|
||||
"type": "string",
|
||||
"maxLength": 2000
|
||||
|
@ -5318,6 +5334,10 @@
|
|||
"short_description": {
|
||||
"type": "string",
|
||||
"maxLength": 255
|
||||
},
|
||||
"site_url": {
|
||||
"type": "string",
|
||||
"maxLength": 512
|
||||
}
|
||||
}
|
||||
},
|
||||
|
|
|
@ -983,6 +983,9 @@ definitions:
|
|||
type: object
|
||||
schema.SiteGeneralReq:
|
||||
properties:
|
||||
contact_email:
|
||||
maxLength: 512
|
||||
type: string
|
||||
description:
|
||||
maxLength: 2000
|
||||
type: string
|
||||
|
@ -992,13 +995,21 @@ definitions:
|
|||
short_description:
|
||||
maxLength: 255
|
||||
type: string
|
||||
site_url:
|
||||
maxLength: 512
|
||||
type: string
|
||||
required:
|
||||
- contact_email
|
||||
- description
|
||||
- name
|
||||
- short_description
|
||||
- site_url
|
||||
type: object
|
||||
schema.SiteGeneralResp:
|
||||
properties:
|
||||
contact_email:
|
||||
maxLength: 512
|
||||
type: string
|
||||
description:
|
||||
maxLength: 2000
|
||||
type: string
|
||||
|
@ -1008,10 +1019,15 @@ definitions:
|
|||
short_description:
|
||||
maxLength: 255
|
||||
type: string
|
||||
site_url:
|
||||
maxLength: 512
|
||||
type: string
|
||||
required:
|
||||
- contact_email
|
||||
- description
|
||||
- name
|
||||
- short_description
|
||||
- site_url
|
||||
type: object
|
||||
schema.SiteInterfaceReq:
|
||||
properties:
|
||||
|
|
|
@ -0,0 +1 @@
|
|||
package controller
|
|
@ -29,7 +29,7 @@ func NewDashboardController(
|
|||
// @Router /answer/admin/api/dashboard [get]
|
||||
// @Success 200 {object} handler.RespBody
|
||||
func (ac *DashboardController) DashboardInfo(ctx *gin.Context) {
|
||||
info, err := ac.dashboardService.Statistical(ctx)
|
||||
info, err := ac.dashboardService.StatisticalByCache(ctx)
|
||||
handler.HandleResponse(ctx, err, gin.H{
|
||||
"info": info,
|
||||
})
|
||||
|
|
|
@ -4,6 +4,11 @@ import "time"
|
|||
|
||||
var AppStartTime time.Time
|
||||
|
||||
const (
|
||||
DashBoardCachekey = "answer@dashboard"
|
||||
DashBoardCacheTime = 60 * time.Minute
|
||||
)
|
||||
|
||||
type DashboardInfo struct {
|
||||
QuestionCount int64 `json:"question_count"`
|
||||
AnswerCount int64 `json:"answer_count"`
|
||||
|
|
|
@ -6,9 +6,11 @@ import (
|
|||
"fmt"
|
||||
"io/ioutil"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"time"
|
||||
|
||||
"github.com/answerdev/answer/internal/base/constant"
|
||||
"github.com/answerdev/answer/internal/base/data"
|
||||
"github.com/answerdev/answer/internal/base/reason"
|
||||
"github.com/answerdev/answer/internal/schema"
|
||||
"github.com/answerdev/answer/internal/service/activity_common"
|
||||
|
@ -18,8 +20,10 @@ import (
|
|||
"github.com/answerdev/answer/internal/service/export"
|
||||
questioncommon "github.com/answerdev/answer/internal/service/question_common"
|
||||
"github.com/answerdev/answer/internal/service/report_common"
|
||||
"github.com/answerdev/answer/internal/service/service_config"
|
||||
"github.com/answerdev/answer/internal/service/siteinfo_common"
|
||||
usercommon "github.com/answerdev/answer/internal/service/user_common"
|
||||
"github.com/answerdev/answer/pkg/dir"
|
||||
"github.com/segmentfault/pacman/errors"
|
||||
"github.com/segmentfault/pacman/log"
|
||||
)
|
||||
|
@ -33,6 +37,9 @@ type DashboardService struct {
|
|||
reportRepo report_common.ReportRepo
|
||||
configRepo config.ConfigRepo
|
||||
siteInfoService *siteinfo_common.SiteInfoCommonService
|
||||
serviceConfig *service_config.ServiceConfig
|
||||
|
||||
data *data.Data
|
||||
}
|
||||
|
||||
func NewDashboardService(
|
||||
|
@ -44,6 +51,9 @@ func NewDashboardService(
|
|||
reportRepo report_common.ReportRepo,
|
||||
configRepo config.ConfigRepo,
|
||||
siteInfoService *siteinfo_common.SiteInfoCommonService,
|
||||
serviceConfig *service_config.ServiceConfig,
|
||||
|
||||
data *data.Data,
|
||||
) *DashboardService {
|
||||
return &DashboardService{
|
||||
questionRepo: questionRepo,
|
||||
|
@ -54,9 +64,47 @@ func NewDashboardService(
|
|||
reportRepo: reportRepo,
|
||||
configRepo: configRepo,
|
||||
siteInfoService: siteInfoService,
|
||||
serviceConfig: serviceConfig,
|
||||
|
||||
data: data,
|
||||
}
|
||||
}
|
||||
|
||||
func (ds *DashboardService) StatisticalByCache(ctx context.Context) (*schema.DashboardInfo, error) {
|
||||
dashboardInfo := &schema.DashboardInfo{}
|
||||
infoStr, err := ds.data.Cache.GetString(ctx, schema.DashBoardCachekey)
|
||||
if err != nil {
|
||||
info, statisticalErr := ds.Statistical(ctx)
|
||||
if statisticalErr != nil {
|
||||
return dashboardInfo, err
|
||||
}
|
||||
setCacheErr := ds.SetCache(ctx, info)
|
||||
if setCacheErr != nil {
|
||||
log.Error("ds.SetCache", setCacheErr)
|
||||
}
|
||||
return info, err
|
||||
}
|
||||
err = json.Unmarshal([]byte(infoStr), dashboardInfo)
|
||||
if err != nil {
|
||||
return dashboardInfo, err
|
||||
}
|
||||
startTime := time.Now().Unix() - schema.AppStartTime.Unix()
|
||||
dashboardInfo.AppStartTime = fmt.Sprintf("%d", startTime)
|
||||
return dashboardInfo, nil
|
||||
}
|
||||
|
||||
func (ds *DashboardService) SetCache(ctx context.Context, info *schema.DashboardInfo) error {
|
||||
infoStr, err := json.Marshal(info)
|
||||
if err != nil {
|
||||
return errors.InternalServer(reason.UnknownError).WithError(err).WithStack()
|
||||
}
|
||||
err = ds.data.Cache.SetString(ctx, schema.DashBoardCachekey, string(infoStr), schema.DashBoardCacheTime)
|
||||
if err != nil {
|
||||
return errors.InternalServer(reason.UnknownError).WithError(err).WithStack()
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// Statistical
|
||||
func (ds *DashboardService) Statistical(ctx context.Context) (*schema.DashboardInfo, error) {
|
||||
dashboardInfo := &schema.DashboardInfo{}
|
||||
|
@ -124,8 +172,24 @@ func (ds *DashboardService) Statistical(ctx context.Context) (*schema.DashboardI
|
|||
if emailconfig.SMTPHost != "" {
|
||||
dashboardInfo.SMTP = true
|
||||
}
|
||||
dashboardInfo.HTTPS = true
|
||||
dashboardInfo.OccupyingStorageSpace = "1MB"
|
||||
siteGeneral, err := ds.siteInfoService.GetSiteGeneral(ctx)
|
||||
if err != nil {
|
||||
return dashboardInfo, err
|
||||
}
|
||||
siteUrl, err := url.Parse(siteGeneral.SiteUrl)
|
||||
if err != nil {
|
||||
return dashboardInfo, err
|
||||
}
|
||||
if siteUrl.Scheme == "https" {
|
||||
dashboardInfo.HTTPS = true
|
||||
}
|
||||
|
||||
dirSize, err := dir.DirSize(ds.serviceConfig.UploadPath)
|
||||
if err != nil {
|
||||
return dashboardInfo, err
|
||||
}
|
||||
size := dir.FormatFileSize(dirSize)
|
||||
dashboardInfo.OccupyingStorageSpace = size
|
||||
startTime := time.Now().Unix() - schema.AppStartTime.Unix()
|
||||
dashboardInfo.AppStartTime = fmt.Sprintf("%d", startTime)
|
||||
dashboardInfo.TimeZone = siteInfoInterface.TimeZone
|
||||
|
|
|
@ -1,6 +1,10 @@
|
|||
package dir
|
||||
|
||||
import "os"
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"path/filepath"
|
||||
)
|
||||
|
||||
func CreateDirIfNotExist(path string) error {
|
||||
return os.MkdirAll(path, os.ModePerm)
|
||||
|
@ -15,3 +19,32 @@ func CheckFileExist(path string) bool {
|
|||
f, err := os.Stat(path)
|
||||
return err == nil && !f.IsDir()
|
||||
}
|
||||
|
||||
func DirSize(path string) (int64, error) {
|
||||
var size int64
|
||||
err := filepath.Walk(path, func(_ string, info os.FileInfo, err error) error {
|
||||
if !info.IsDir() {
|
||||
size += info.Size()
|
||||
}
|
||||
return err
|
||||
})
|
||||
return size, err
|
||||
}
|
||||
|
||||
func FormatFileSize(fileSize int64) (size string) {
|
||||
if fileSize < 1024 {
|
||||
//return strconv.FormatInt(fileSize, 10) + "B"
|
||||
return fmt.Sprintf("%.2f B", float64(fileSize)/float64(1))
|
||||
} else if fileSize < (1024 * 1024) {
|
||||
return fmt.Sprintf("%.2f KB", float64(fileSize)/float64(1024))
|
||||
} else if fileSize < (1024 * 1024 * 1024) {
|
||||
return fmt.Sprintf("%.2f MB", float64(fileSize)/float64(1024*1024))
|
||||
} else if fileSize < (1024 * 1024 * 1024 * 1024) {
|
||||
return fmt.Sprintf("%.2f GB", float64(fileSize)/float64(1024*1024*1024))
|
||||
} else if fileSize < (1024 * 1024 * 1024 * 1024 * 1024) {
|
||||
return fmt.Sprintf("%.2f TB", float64(fileSize)/float64(1024*1024*1024*1024))
|
||||
} else { //if fileSize < (1024 * 1024 * 1024 * 1024 * 1024 * 1024)
|
||||
return fmt.Sprintf("%.2f EB", float64(fileSize)/float64(1024*1024*1024*1024*1024))
|
||||
}
|
||||
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue