diff --git a/backend/app/api/v1/clam.go b/backend/app/api/v1/clam.go index f6a3428b2..b044dd1ce 100644 --- a/backend/app/api/v1/clam.go +++ b/backend/app/api/v1/clam.go @@ -163,6 +163,29 @@ func (b *BaseApi) SearchClamRecord(c *gin.Context) { }) } +// @Tags Clam +// @Summary Load clam record detail +// @Description 获取扫描结果详情 +// @Accept json +// @Param request body dto.ClamLogReq true "request" +// @Success 200 +// @Security ApiKeyAuth +// @Router /toolbox/clam/record/log [post] +func (b *BaseApi) LoadClamRecordLog(c *gin.Context) { + var req dto.ClamLogReq + if err := helper.CheckBindAndValidate(&req, c); err != nil { + return + } + + content, err := clamService.LoadRecordLog(req) + if err != nil { + helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err) + return + } + + helper.SuccessWithData(c, content) +} + // @Tags Clam // @Summary Load clam file // @Description 获取扫描文件 diff --git a/backend/app/dto/clam.go b/backend/app/dto/clam.go index a526d64fd..72cce4a97 100644 --- a/backend/app/dto/clam.go +++ b/backend/app/dto/clam.go @@ -30,12 +30,18 @@ type ClamLogSearch struct { EndTime time.Time `json:"endTime"` } +type ClamLogReq struct { + Tail string `json:"tail"` + ClamName string `json:"clamName"` + RecordName string `json:"recordName"` +} + type ClamLog struct { Name string `json:"name"` ScanDate string `json:"scanDate"` ScanTime string `json:"scanTime"` InfectedFiles string `json:"infectedFiles"` - Log string `json:"log"` + TotalError string `json:"totalError"` Status string `json:"status"` } @@ -58,7 +64,7 @@ type ClamUpdate struct { } type ClamDelete struct { - RemoveResult bool `json:"removeResult"` + RemoveRecord bool `json:"removeRecord"` RemoveInfected bool `json:"removeInfected"` Ids []uint `json:"ids" validate:"required"` } diff --git a/backend/app/service/clam.go b/backend/app/service/clam.go index 8efd5ea70..51aaa3b97 100644 --- a/backend/app/service/clam.go +++ b/backend/app/service/clam.go @@ -45,6 +45,8 @@ type IClamService interface { UpdateFile(req dto.UpdateByNameAndFile) error LoadRecords(req dto.ClamLogSearch) (int64, interface{}, error) CleanRecord(req dto.OperateByID) error + + LoadRecordLog(req dto.ClamLogReq) (string, error) } func NewIClamService() IClamService { @@ -160,7 +162,7 @@ func (u *ClamService) Delete(req dto.ClamDelete) error { if clam.ID == 0 { continue } - if req.RemoveResult { + if req.RemoveRecord { _ = os.RemoveAll(path.Join(global.CONF.System.DataDir, resultDir, clam.Name)) } if req.RemoveInfected { @@ -255,6 +257,21 @@ func (u *ClamService) LoadRecords(req dto.ClamLogSearch) (int64, interface{}, er } return int64(total), datas, nil } +func (u *ClamService) LoadRecordLog(req dto.ClamLogReq) (string, error) { + logPath := path.Join(global.CONF.System.DataDir, resultDir, req.ClamName, req.RecordName) + var tail string + if req.Tail != "0" { + tail = req.Tail + } else { + tail = "+1" + } + cmd := exec.Command("tail", "-n", tail, logPath) + stdout, err := cmd.CombinedOutput() + if err != nil { + return "", fmt.Errorf("tail -n %v failed, err: %v", req.Tail, err) + } + return string(stdout), nil +} func (u *ClamService) CleanRecord(req dto.OperateByID) error { clam, _ := clamRepo.Get(commonRepo.WithByID(req.ID)) @@ -364,7 +381,6 @@ func loadResultFromLog(pathItem string) dto.ClamLog { if err != nil { return data } - data.Log = string(file) lines := strings.Split(string(file), "\n") for _, line := range lines { if strings.Contains(line, "- SCAN SUMMARY -") { @@ -376,6 +392,8 @@ func loadResultFromLog(pathItem string) dto.ClamLog { switch { case strings.HasPrefix(line, "Infected files:"): data.InfectedFiles = strings.TrimPrefix(line, "Infected files:") + case strings.HasPrefix(line, "Total errors:"): + data.TotalError = strings.TrimPrefix(line, "Total errors:") case strings.HasPrefix(line, "Time:"): if strings.Contains(line, "(") { data.ScanTime = strings.ReplaceAll(strings.Split(line, "(")[1], ")", "") diff --git a/backend/router/ro_toolbox.go b/backend/router/ro_toolbox.go index be3b80f6b..52b79d9a4 100644 --- a/backend/router/ro_toolbox.go +++ b/backend/router/ro_toolbox.go @@ -49,6 +49,7 @@ func (s *ToolboxRouter) InitRouter(Router *gin.RouterGroup) { toolboxRouter.POST("/clam/search", baseApi.SearchClam) toolboxRouter.POST("/clam/record/search", baseApi.SearchClamRecord) toolboxRouter.POST("/clam/record/clean", baseApi.CleanClamRecord) + toolboxRouter.POST("/clam/record/log", baseApi.LoadClamRecordLog) toolboxRouter.POST("/clam/file/search", baseApi.SearchClamFile) toolboxRouter.POST("/clam/file/update", baseApi.UpdateFile) toolboxRouter.POST("/clam", baseApi.CreateClam) diff --git a/cmd/server/docs/docs.go b/cmd/server/docs/docs.go index 5c8d07047..bbfbb09ee 100644 --- a/cmd/server/docs/docs.go +++ b/cmd/server/docs/docs.go @@ -11395,6 +11395,39 @@ const docTemplate = `{ } } }, + "/toolbox/clam/record/log": { + "post": { + "security": [ + { + "ApiKeyAuth": [] + } + ], + "description": "获取扫描结果详情", + "consumes": [ + "application/json" + ], + "tags": [ + "Clam" + ], + "summary": "Load clam record detail", + "parameters": [ + { + "description": "request", + "name": "request", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/dto.ClamLogReq" + } + } + ], + "responses": { + "200": { + "description": "OK" + } + } + } + }, "/toolbox/clam/record/search": { "post": { "security": [ @@ -15495,11 +15528,25 @@ const docTemplate = `{ "removeInfected": { "type": "boolean" }, - "removeResult": { + "removeRecord": { "type": "boolean" } } }, + "dto.ClamLogReq": { + "type": "object", + "properties": { + "clamName": { + "type": "string" + }, + "recordName": { + "type": "string" + }, + "tail": { + "type": "string" + } + } + }, "dto.ClamLogSearch": { "type": "object", "required": [ diff --git a/cmd/server/docs/swagger.json b/cmd/server/docs/swagger.json index 02a221629..020f746b0 100644 --- a/cmd/server/docs/swagger.json +++ b/cmd/server/docs/swagger.json @@ -11388,6 +11388,39 @@ } } }, + "/toolbox/clam/record/log": { + "post": { + "security": [ + { + "ApiKeyAuth": [] + } + ], + "description": "获取扫描结果详情", + "consumes": [ + "application/json" + ], + "tags": [ + "Clam" + ], + "summary": "Load clam record detail", + "parameters": [ + { + "description": "request", + "name": "request", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/dto.ClamLogReq" + } + } + ], + "responses": { + "200": { + "description": "OK" + } + } + } + }, "/toolbox/clam/record/search": { "post": { "security": [ @@ -15488,11 +15521,25 @@ "removeInfected": { "type": "boolean" }, - "removeResult": { + "removeRecord": { "type": "boolean" } } }, + "dto.ClamLogReq": { + "type": "object", + "properties": { + "clamName": { + "type": "string" + }, + "recordName": { + "type": "string" + }, + "tail": { + "type": "string" + } + } + }, "dto.ClamLogSearch": { "type": "object", "required": [ diff --git a/cmd/server/docs/swagger.yaml b/cmd/server/docs/swagger.yaml index 4698ac49c..74b455c0a 100644 --- a/cmd/server/docs/swagger.yaml +++ b/cmd/server/docs/swagger.yaml @@ -246,11 +246,20 @@ definitions: type: array removeInfected: type: boolean - removeResult: + removeRecord: type: boolean required: - ids type: object + dto.ClamLogReq: + properties: + clamName: + type: string + recordName: + type: string + tail: + type: string + type: object dto.ClamLogSearch: properties: clamID: @@ -12669,6 +12678,26 @@ paths: formatEN: clean clam record [name] formatZH: 清空扫描报告 [name] paramKeys: [] + /toolbox/clam/record/log: + post: + consumes: + - application/json + description: 获取扫描结果详情 + parameters: + - description: request + in: body + name: request + required: true + schema: + $ref: '#/definitions/dto.ClamLogReq' + responses: + "200": + description: OK + security: + - ApiKeyAuth: [] + summary: Load clam record detail + tags: + - Clam /toolbox/clam/record/search: post: consumes: diff --git a/frontend/src/api/interface/toolbox.ts b/frontend/src/api/interface/toolbox.ts index 2c033c92b..1f290d15a 100644 --- a/frontend/src/api/interface/toolbox.ts +++ b/frontend/src/api/interface/toolbox.ts @@ -151,13 +151,17 @@ export namespace Toolbox { startTime: Date; endTime: Date; } + export interface ClamRecordReq { + tail: string; + clamName: string; + recordName: string; + } export interface ClamLog { name: string; scanDate: string; scanTime: string; - scannedFiles: string; + totalError: string; infectedFiles: string; - log: string; status: string; } } diff --git a/frontend/src/api/modules/toolbox.ts b/frontend/src/api/modules/toolbox.ts index 0c43add65..aa5f529d3 100644 --- a/frontend/src/api/modules/toolbox.ts +++ b/frontend/src/api/modules/toolbox.ts @@ -114,6 +114,9 @@ export const cleanClamRecord = (id: number) => { export const searchClamRecord = (param: Toolbox.ClamSearchLog) => { return http.post>(`/toolbox/clam/record/search`, param); }; +export const getClamRecordLog = (param: Toolbox.ClamRecordReq) => { + return http.post(`/toolbox/clam/record/log`, param); +}; export const searchClamFile = (name: string) => { return http.post(`/toolbox/clam/file/search`, { name: name }); }; @@ -135,7 +138,7 @@ export const createClam = (params: Toolbox.ClamCreate) => { export const updateClam = (params: Toolbox.ClamUpdate) => { return http.post(`/toolbox/clam/update`, params); }; -export const deleteClam = (params: { ids: number[]; removeResult: boolean; removeInfected: boolean }) => { +export const deleteClam = (params: { ids: number[]; removeRecord: boolean; removeInfected: boolean }) => { return http.post(`/toolbox/clam/del`, params); }; export const handleClamScan = (id: number) => { diff --git a/frontend/src/lang/modules/en.ts b/frontend/src/lang/modules/en.ts index b4fc0e698..63a5a2be1 100644 --- a/frontend/src/lang/modules/en.ts +++ b/frontend/src/lang/modules/en.ts @@ -1081,7 +1081,7 @@ const message = { removeInfectedHelper: 'Delete virus files detected during the task to ensure server security and normal operation.', clamCreate: 'Create Scan Rules', - infectedStrategy: 'Virus Strategy', + infectedStrategy: 'Infected Strategy', remove: 'Delete', removeHelper: 'Delete virus files, choose carefully!', move: 'Move', @@ -1093,8 +1093,8 @@ const message = { scanDir: 'Scan Directory', infectedDir: 'Infected Directory', scanDate: 'Scan Date', + scanResult: 'Scan log tail', scanTime: 'Time Taken', - scannedFiles: 'Scanned Files', infectedFiles: 'Infected Files', log: 'Details', clamConf: 'Scan Configuration', diff --git a/frontend/src/lang/modules/tw.ts b/frontend/src/lang/modules/tw.ts index f595383a6..ca7d728c3 100644 --- a/frontend/src/lang/modules/tw.ts +++ b/frontend/src/lang/modules/tw.ts @@ -1022,7 +1022,7 @@ const message = { removeInfected: '刪除病毒文件', removeInfectedHelper: '刪除任務檢測到的病毒文件,以確保伺服器的安全和正常運行。', clamCreate: '創建掃描規則', - infectedStrategy: '病毒策略', + infectedStrategy: '感染文件策略', remove: '刪除', removeHelper: '刪除病毒文件,請謹慎選擇!', move: '移動', @@ -1032,11 +1032,11 @@ const message = { none: '不操作', noneHelper: '不對病毒文件採取任何操作', scanDir: '掃描目錄', - infectedDir: '病毒目錄', + infectedDir: '隔離目錄', scanDate: '掃描時間', + scanResult: '掃描報告條數', scanTime: '耗時', - scannedFiles: '掃描文件數', - infectedFiles: '危險文件數', + infectedFiles: '感染文件數', log: '詳情', clamConf: '掃描配置', clamLog: '掃描日誌', diff --git a/frontend/src/lang/modules/zh.ts b/frontend/src/lang/modules/zh.ts index ab9cad7c8..2d98b03e5 100644 --- a/frontend/src/lang/modules/zh.ts +++ b/frontend/src/lang/modules/zh.ts @@ -1023,7 +1023,7 @@ const message = { removeInfected: '删除病毒文件', removeInfectedHelper: '删除任务检测到的病毒文件,以确保服务器的安全和正常运行。', clamCreate: '创建扫描规则', - infectedStrategy: '病毒策略', + infectedStrategy: '感染文件策略', remove: '删除', removeHelper: '删除病毒文件,请谨慎选择!', move: '移动', @@ -1033,11 +1033,11 @@ const message = { none: '不操作', noneHelper: '不对病毒文件采取任何操作', scanDir: '扫描目录', - infectedDir: '病毒目录', + infectedDir: '隔离目录', scanDate: '扫描时间', + scanResult: '扫描报告条数', scanTime: '耗时', - scannedFiles: '扫描文件数', - infectedFiles: '危险文件数', + infectedFiles: '感染文件数', log: '详情', clamConf: '扫描配置', clamLog: '扫描日志', diff --git a/frontend/src/views/cronjob/record/index.vue b/frontend/src/views/cronjob/record/index.vue index 7bf7e28d9..587cf6f3f 100644 --- a/frontend/src/views/cronjob/record/index.vue +++ b/frontend/src/views/cronjob/record/index.vue @@ -236,7 +236,7 @@