2
0
mirror of https://github.com/acepanel/panel.git synced 2026-02-04 04:22:33 +08:00

feat: add date selector for viewing archived panel logs (#1316)

* Initial plan

* feat: add date selector for log viewing

- Add date parameter to log list API
- Add log dates listing API
- Update frontend with date selector in all log views
- Add translations for Date field

Co-authored-by: devhaozi <115467771+devhaozi@users.noreply.github.com>

* refactor: cache regex patterns to avoid recompilation overhead

Co-authored-by: devhaozi <115467771+devhaozi@users.noreply.github.com>

* refactor: use predefined regex constants instead of sync.Map

Simplified the regex caching by using predefined package-level constants
for the three log types (app, db, http) instead of sync.Map.

Co-authored-by: devhaozi <115467771+devhaozi@users.noreply.github.com>

* fix: lint

---------

Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: devhaozi <115467771+devhaozi@users.noreply.github.com>
Co-authored-by: 耗子 <haozi@loli.email>
This commit is contained in:
Copilot
2026-02-03 00:04:43 +08:00
committed by GitHub
parent 15f096191e
commit 4f19a58bba
13 changed files with 2614 additions and 3026 deletions

View File

@@ -47,5 +47,8 @@ type LogEntry struct {
// LogRepo 日志仓库接口
type LogRepo interface {
// List 获取日志列表
List(logType string, limit int) ([]LogEntry, error)
// date 格式为 YYYY-MM-DD空字符串表示当天日志
List(logType string, limit int, date string) ([]LogEntry, error)
// ListDates 获取可用的日志日期列表
ListDates(logType string) ([]string, error)
}

View File

@@ -5,6 +5,8 @@ import (
"encoding/json"
"os"
"path/filepath"
"regexp"
"sort"
"strings"
"time"
@@ -14,6 +16,12 @@ import (
"github.com/acepanel/panel/internal/biz"
)
var (
logArchivePatternApp = regexp.MustCompile(`^app-(\d{4}-\d{2}-\d{2})T.*\.log$`)
logArchivePatternDB = regexp.MustCompile(`^db-(\d{4}-\d{2}-\d{2})T.*\.log$`)
logArchivePatternHTTP = regexp.MustCompile(`^http-(\d{4}-\d{2}-\d{2})T.*\.log$`)
)
type logRepo struct {
db *gorm.DB
}
@@ -25,20 +33,43 @@ func NewLogRepo(db *gorm.DB) biz.LogRepo {
}
// List 获取日志列表
func (r *logRepo) List(logType string, limit int) ([]biz.LogEntry, error) {
var filename string
switch logType {
case biz.LogTypeApp:
filename = "app.log"
case biz.LogTypeDB:
filename = "db.log"
case biz.LogTypeHTTP:
filename = "http.log"
default:
filename = "app.log"
}
// date 格式为 YYYY-MM-DD空字符串表示当天日志
func (r *logRepo) List(logType string, limit int, date string) ([]biz.LogEntry, error) {
logDir := filepath.Join(app.Root, "panel/storage/logs")
logPath := filepath.Join(app.Root, "panel/storage/logs", filename)
var logPath string
if date == "" {
// 无日期参数,读取当前日志文件
logPath = filepath.Join(logDir, logType+".log")
} else {
// 有日期参数,查找对应的归档日志文件
pattern := getLogArchivePattern(logType)
entries, err := os.ReadDir(logDir)
if err != nil {
if os.IsNotExist(err) {
return []biz.LogEntry{}, nil
}
return nil, err
}
found := false
for _, entry := range entries {
if entry.IsDir() {
continue
}
matches := pattern.FindStringSubmatch(entry.Name())
if len(matches) == 2 && matches[1] == date {
logPath = filepath.Join(logDir, entry.Name())
found = true
break
}
}
if !found {
return []biz.LogEntry{}, nil
}
}
file, err := os.Open(logPath)
if err != nil {
@@ -92,6 +123,37 @@ func (r *logRepo) List(logType string, limit int) ([]biz.LogEntry, error) {
return entries, nil
}
// ListDates 获取可用的日志日期列表
func (r *logRepo) ListDates(logType string) ([]string, error) {
logDir := filepath.Join(app.Root, "panel/storage/logs")
entries, err := os.ReadDir(logDir)
if err != nil {
if os.IsNotExist(err) {
return []string{}, nil
}
return nil, err
}
pattern := getLogArchivePattern(logType)
dates := make([]string, 0)
for _, entry := range entries {
if entry.IsDir() {
continue
}
matches := pattern.FindStringSubmatch(entry.Name())
if len(matches) == 2 {
dates = append(dates, matches[1])
}
}
// 按日期倒序排列,最新的在前面
sort.Sort(sort.Reverse(sort.StringSlice(dates)))
return dates, nil
}
// fillOperatorNames 填充操作员用户名
func (r *logRepo) fillOperatorNames(entries []biz.LogEntry) {
// 收集所有用户ID
@@ -177,3 +239,17 @@ func (r *logRepo) parseLine(line string, logType string) (biz.LogEntry, error) {
return entry, nil
}
// getLogArchivePattern 获取归档日志文件名匹配正则表达式
func getLogArchivePattern(logType string) *regexp.Regexp {
switch logType {
case biz.LogTypeApp:
return logArchivePatternApp
case biz.LogTypeDB:
return logArchivePatternDB
case biz.LogTypeHTTP:
return logArchivePatternHTTP
default:
return logArchivePatternApp
}
}

View File

@@ -4,4 +4,10 @@ package request
type LogList struct {
Type string `json:"type" form:"type" query:"type" validate:"required|in:app,db,http"`
Limit int `json:"limit" form:"limit" query:"limit" validate:"min:1|max:1000"`
Date string `json:"date" form:"date" query:"date"` // 日期,格式为 YYYY-MM-DD空表示当天
}
// LogDates 日志日期列表请求
type LogDates struct {
Type string `json:"type" form:"type" query:"type" validate:"required|in:app,db,http"`
}

View File

@@ -477,6 +477,7 @@ func (route *Http) Register(r *chi.Mux) {
r.Route("/log", func(r chi.Router) {
r.Get("/list", route.log.List)
r.Get("/dates", route.log.Dates)
})
r.Route("/monitor", func(r chi.Router) {

View File

@@ -30,7 +30,7 @@ func (s *LogService) List(w http.ResponseWriter, r *http.Request) {
req.Limit = 100
}
entries, err := s.logRepo.List(req.Type, req.Limit)
entries, err := s.logRepo.List(req.Type, req.Limit, req.Date)
if err != nil {
Error(w, http.StatusInternalServerError, "%v", err)
return
@@ -38,3 +38,20 @@ func (s *LogService) List(w http.ResponseWriter, r *http.Request) {
Success(w, entries)
}
// Dates 获取日志日期列表
func (s *LogService) Dates(w http.ResponseWriter, r *http.Request) {
req, err := Bind[request.LogDates](r)
if err != nil {
Error(w, http.StatusUnprocessableEntity, "%v", err)
return
}
dates, err := s.logRepo.ListDates(req.Type)
if err != nil {
Error(w, http.StatusInternalServerError, "%v", err)
return
}
Success(w, dates)
}

View File

@@ -2,6 +2,9 @@ import { http } from '@/utils'
export default {
// 获取日志列表
list: (type: 'app' | 'db' | 'http', limit: number = 100): any =>
http.Get('/log/list', { params: { type, limit } })
list: (type: 'app' | 'db' | 'http', limit: number = 100, date: string = ''): any =>
http.Get('/log/list', { params: { type, limit, date } }),
// 获取日志日期列表
dates: (type: 'app' | 'db' | 'http'): any => http.Get('/log/dates', { params: { type } })
}

View File

@@ -40,37 +40,37 @@ msgstr "Sponsor"
#: src/components/common/CronPreview.vue:15
#: src/components/common/CronPreview.vue:22
#: src/components/common/CronSelector.vue:142
#: src/components/common/CronSelector.vue:163
msgid "Sunday"
msgstr ""
#: src/components/common/CronPreview.vue:16
#: src/components/common/CronSelector.vue:143
#: src/components/common/CronSelector.vue:164
msgid "Monday"
msgstr ""
#: src/components/common/CronPreview.vue:17
#: src/components/common/CronSelector.vue:144
#: src/components/common/CronSelector.vue:165
msgid "Tuesday"
msgstr ""
#: src/components/common/CronPreview.vue:18
#: src/components/common/CronSelector.vue:145
#: src/components/common/CronSelector.vue:166
msgid "Wednesday"
msgstr ""
#: src/components/common/CronPreview.vue:19
#: src/components/common/CronSelector.vue:146
#: src/components/common/CronSelector.vue:167
msgid "Thursday"
msgstr ""
#: src/components/common/CronPreview.vue:20
#: src/components/common/CronSelector.vue:147
#: src/components/common/CronSelector.vue:168
msgid "Friday"
msgstr ""
#: src/components/common/CronPreview.vue:21
#: src/components/common/CronSelector.vue:148
#: src/components/common/CronSelector.vue:169
msgid "Saturday"
msgstr ""
@@ -116,40 +116,45 @@ msgstr ""
msgid "Run every minute"
msgstr ""
#: src/components/common/CronSelector.vue:129
#: src/components/common/CronSelector.vue:149
#, fuzzy
msgid "Every Minute"
msgstr "minutes"
#: src/components/common/CronSelector.vue:150
msgid "Every N Minutes"
msgstr ""
#: src/components/common/CronSelector.vue:130
#: src/components/common/CronSelector.vue:151
msgid "Every N Hours"
msgstr ""
#: src/components/common/CronSelector.vue:131
#: src/components/common/CronSelector.vue:152
#, fuzzy
msgid "Every N Days"
msgstr "Save Days"
#: src/components/common/CronSelector.vue:132
#: src/components/common/CronSelector.vue:153
msgid "Hourly"
msgstr ""
#: src/components/common/CronSelector.vue:133
#: src/components/common/CronSelector.vue:154
msgid "Daily"
msgstr ""
#: src/components/common/CronSelector.vue:134
#: src/components/common/CronSelector.vue:155
msgid "Weekly"
msgstr ""
#: src/components/common/CronSelector.vue:135
#: src/components/common/CronSelector.vue:156
msgid "Monthly"
msgstr ""
#: src/components/common/CronSelector.vue:136
#: src/components/common/CronSelector.vue:157
msgid "Yearly"
msgstr ""
#: src/components/common/CronSelector.vue:137
#: src/components/common/CronSelector.vue:158
#: src/views/monitor/IndexView.vue:650 src/views/monitor/IndexView.vue:704
#: src/views/monitor/IndexView.vue:756 src/views/monitor/IndexView.vue:812
#: src/views/monitor/IndexView.vue:879 src/views/project/CreateModal.vue:22
@@ -159,40 +164,40 @@ msgstr ""
msgid "Custom"
msgstr "Custom Logo"
#: src/components/common/CronSelector.vue:153
#: src/components/common/CronSelector.vue:174
msgid "Month %{month}"
msgstr ""
#: src/components/common/CronSelector.vue:276
#: src/components/common/CronSelector.vue:301
#: src/views/apps/nginx/NginxIndex.vue:745 src/views/website/EditView.vue:557
#, fuzzy
msgid "Minutes"
msgstr "minutes"
#: src/components/common/CronSelector.vue:287
#: src/components/common/CronSelector.vue:312
#: src/views/apps/nginx/NginxIndex.vue:746 src/views/website/EditView.vue:558
msgid "Hours"
msgstr ""
#: src/components/common/CronSelector.vue:298
#: src/components/common/CronSelector.vue:323
#, fuzzy
msgid "Days"
msgstr "Save Days"
#: src/components/common/CronSelector.vue:317
#: src/components/common/CronSelector.vue:342
msgid "Day"
msgstr ""
#: src/components/common/CronSelector.vue:336
#: src/components/common/CronSelector.vue:361
msgid "Hour"
msgstr ""
#: src/components/common/CronSelector.vue:347
#: src/components/common/CronSelector.vue:372
#, fuzzy
msgid "Minute"
msgstr "minutes"
#: src/components/common/CronSelector.vue:354
#: src/components/common/CronSelector.vue:379
#, fuzzy
msgid "Enter Cron expression"
msgstr "Enter user password"
@@ -226,36 +231,37 @@ msgstr "Confirm"
#: src/views/container/ImagePullModal.vue:184
#: src/views/container/ImagePullModal.vue:198
#: src/views/container/ImageView.vue:351 src/views/container/ImageView.vue:366
#: src/views/file/ListView.vue:245 src/views/file/ListView.vue:738
#: src/views/file/ListView.vue:863 src/views/file/ToolBar.vue:125
#: src/views/file/ToolBar.vue:260 src/views/file/UploadModal.vue:335
#: src/views/file/UploadModal.vue:444 src/views/home/UpdateView.vue:27
#: src/views/project/EditModal.vue:572 src/views/toolbox/DiskView.vue:407
#: src/views/toolbox/DiskView.vue:432 src/views/toolbox/DiskView.vue:455
#: src/views/toolbox/DiskView.vue:481 src/views/toolbox/DiskView.vue:506
#: src/views/toolbox/DiskView.vue:525 src/views/toolbox/DiskView.vue:548
#: src/views/toolbox/DiskView.vue:569 src/views/toolbox/DiskView.vue:596
#: src/views/toolbox/DiskView.vue:618 src/views/toolbox/DiskView.vue:642
#: src/views/toolbox/DiskView.vue:665 src/views/toolbox/ProcessView.vue:242
#: src/views/file/EditModal.vue:41 src/views/file/ListView.vue:245
#: src/views/file/ListView.vue:738 src/views/file/ListView.vue:863
#: src/views/file/ToolBar.vue:125 src/views/file/ToolBar.vue:260
#: src/views/file/UploadModal.vue:335 src/views/file/UploadModal.vue:444
#: src/views/home/UpdateView.vue:27 src/views/project/EditModal.vue:572
#: src/views/toolbox/DiskView.vue:407 src/views/toolbox/DiskView.vue:432
#: src/views/toolbox/DiskView.vue:455 src/views/toolbox/DiskView.vue:481
#: src/views/toolbox/DiskView.vue:506 src/views/toolbox/DiskView.vue:525
#: src/views/toolbox/DiskView.vue:548 src/views/toolbox/DiskView.vue:569
#: src/views/toolbox/DiskView.vue:596 src/views/toolbox/DiskView.vue:618
#: src/views/toolbox/DiskView.vue:642 src/views/toolbox/DiskView.vue:665
#: src/views/toolbox/ProcessView.vue:242
msgid "Cancel"
msgstr "Cancel"
#: src/components/common/DraggableWindow.vue:259
#: src/components/common/DraggableWindow.vue:274
#, fuzzy
msgid "Minimize"
msgstr "Minimum"
#: src/components/common/DraggableWindow.vue:265
#: src/components/common/DraggableWindow.vue:280
#: src/views/backup/ListView.vue:78
msgid "Restore"
msgstr "Restore"
#: src/components/common/DraggableWindow.vue:265
#: src/components/common/DraggableWindow.vue:280
#, fuzzy
msgid "Maximize"
msgstr "Maximum"
#: src/components/common/DraggableWindow.vue:270
#: src/components/common/DraggableWindow.vue:285
#: src/components/file-editor/EditorPane.vue:125
#: src/components/file-editor/EditorPane.vue:211
#: src/layout/tab/components/ContextMenu.vue:28
@@ -372,7 +378,7 @@ msgid "Modification Time"
msgstr "Modification Time"
#: src/components/common/PathSelector.vue:186 src/views/file/ListView.vue:1232
#: src/views/file/PathInput.vue:30
#: src/views/file/PathInput.vue:41
msgid "Invalid path"
msgstr "Invalid path"
@@ -421,7 +427,7 @@ msgstr "Folder"
msgid "Create"
msgstr "Create"
#: src/components/common/PathSelector.vue:326 src/views/file/PathInput.vue:146
#: src/components/common/PathSelector.vue:326 src/views/file/PathInput.vue:163
msgid "Root Directory"
msgstr "Root Directory"
@@ -657,6 +663,7 @@ msgstr "Reload"
#: src/components/file-editor/EditorPane.vue:123
#: src/components/file-editor/EditorToolbar.vue:98
#: src/views/file/EditModal.vue:38
#, fuzzy
msgid "Unsaved Changes"
msgstr "Save Changes"
@@ -727,6 +734,7 @@ msgid "No changes to save"
msgstr ""
#: src/components/file-editor/EditorToolbar.vue:80
#: src/views/file/EditModal.vue:69
#, fuzzy
msgid "All files saved successfully"
msgstr "Settings saved successfully"
@@ -743,8 +751,8 @@ msgstr ""
#: src/components/file-editor/EditorToolbar.vue:200
#: src/components/file-editor/EditorToolbar.vue:205
#: src/components/file-editor/FileTree.vue:696
#: src/views/log/DatabaseLog.vue:108 src/views/log/HttpLog.vue:133
#: src/views/log/OperationLog.vue:106 src/views/toolbox/ProcessView.vue:329
#: src/views/log/DatabaseLog.vue:131 src/views/log/HttpLog.vue:156
#: src/views/log/OperationLog.vue:129 src/views/toolbox/ProcessView.vue:329
msgid "Refresh"
msgstr "Refresh"
@@ -781,12 +789,13 @@ msgstr ""
#: src/views/apps/supervisor/IndexView.vue:342
#: src/views/environment/GoView.vue:90 src/views/environment/NodejsView.vue:93
#: src/views/environment/PHPView.vue:238 src/views/environment/PHPView.vue:256
#: src/views/environment/PythonView.vue:97 src/views/project/EditModal.vue:575
#: src/views/setting/IndexView.vue:107 src/views/task/CronView.vue:284
#: src/views/toolbox/SshView.vue:239 src/views/toolbox/SystemView.vue:190
#: src/views/toolbox/SystemView.vue:214 src/views/toolbox/SystemView.vue:232
#: src/views/toolbox/SystemView.vue:270 src/views/toolbox/SystemView.vue:342
#: src/views/toolbox/WebHookView.vue:390 src/views/website/EditView.vue:1915
#: src/views/environment/PythonView.vue:97 src/views/file/EditModal.vue:40
#: src/views/project/EditModal.vue:575 src/views/setting/IndexView.vue:107
#: src/views/task/CronView.vue:284 src/views/toolbox/SshView.vue:239
#: src/views/toolbox/SystemView.vue:190 src/views/toolbox/SystemView.vue:214
#: src/views/toolbox/SystemView.vue:232 src/views/toolbox/SystemView.vue:270
#: src/views/toolbox/SystemView.vue:342 src/views/toolbox/WebHookView.vue:390
#: src/views/website/EditView.vue:1915
msgid "Save"
msgstr "Save"
@@ -1035,7 +1044,7 @@ msgstr ""
msgid "Format On Type"
msgstr "Format"
#: src/components/file-editor/FileTree.vue:154 src/views/file/EditModal.vue:48
#: src/components/file-editor/FileTree.vue:154 src/views/file/EditModal.vue:105
#, fuzzy
msgid "Failed to load file"
msgstr "Failed to calculate size"
@@ -1092,7 +1101,7 @@ msgstr "Rename"
#: src/views/firewall/IpRuleView.vue:145 src/views/firewall/RuleView.vue:182
#: src/views/project/ListView.vue:198 src/views/project/ListView.vue:306
#: src/views/setting/SettingUser.vue:139 src/views/setting/TokenModal.vue:91
#: src/views/ssh/IndexView.vue:123 src/views/task/CronView.vue:166
#: src/views/ssh/IndexView.vue:124 src/views/task/CronView.vue:166
#: src/views/task/TaskView.vue:97 src/views/toolbox/WebHookView.vue:179
#: src/views/website/ListView.vue:257 src/views/website/ListView.vue:351
msgid "Delete"
@@ -2043,7 +2052,7 @@ msgstr "This modifies the Docker configuration file (/etc/docker/daemon.json)"
#: src/views/container/ComposeView.vue:84
#: src/views/container/ContainerView.vue:50
#: src/views/database/ServerList.vue:142 src/views/database/UserList.vue:131
#: src/views/firewall/RuleView.vue:61 src/views/log/HttpLog.vue:74
#: src/views/firewall/RuleView.vue:61 src/views/log/HttpLog.vue:90
#: src/views/project/ListView.vue:57 src/views/task/TaskView.vue:22
#: src/views/toolbox/ProcessView.vue:137 src/views/toolbox/ProcessView.vue:394
msgid "Status"
@@ -2142,7 +2151,7 @@ msgstr ""
#: src/views/cert/DnsView.vue:38 src/views/database/CreateServerModal.vue:63
#: src/views/database/DatabaseList.vue:12 src/views/database/ServerList.vue:45
#: src/views/database/UserList.vue:17 src/views/file/PropertyModal.vue:33
#: src/views/log/OperationLog.vue:57 src/views/project/ListView.vue:49
#: src/views/log/OperationLog.vue:73 src/views/project/ListView.vue:49
msgid "Type"
msgstr "Type"
@@ -2166,7 +2175,7 @@ msgstr "Protection Mode"
#: src/views/backup/StorageView.vue:271 src/views/backup/StorageView.vue:325
#: src/views/backup/StorageView.vue:355 src/views/backup/StorageView.vue:419
#: src/views/backup/StorageView.vue:473 src/views/backup/StorageView.vue:503
#: src/views/log/HttpLog.vue:64
#: src/views/log/HttpLog.vue:80
msgid "Path"
msgstr "Path"
@@ -2320,7 +2329,7 @@ msgstr "Proxy Address"
#: src/views/apps/nginx/NginxIndex.vue:273 src/views/backup/StorageView.vue:106
#: src/views/container/ComposeView.vue:122 src/views/file/ListView.vue:332
#: src/views/file/ListView.vue:1568 src/views/project/ListView.vue:179
#: src/views/ssh/IndexView.vue:105 src/views/task/CronView.vue:145
#: src/views/ssh/IndexView.vue:106 src/views/task/CronView.vue:145
#: src/views/toolbox/WebHookView.vue:158 src/views/website/ListView.vue:200
msgid "Edit"
msgstr "Edit"
@@ -3003,8 +3012,8 @@ msgstr "Restore Backup"
msgid "Private Key"
msgstr "Private Key"
#: src/views/backup/StorageView.vue:72 src/views/ssh/IndexView.vue:63
#: src/views/ssh/IndexView.vue:72
#: src/views/backup/StorageView.vue:72 src/views/ssh/IndexView.vue:64
#: src/views/ssh/IndexView.vue:73
msgid "Local"
msgstr ""
@@ -4525,7 +4534,17 @@ msgstr "Compress to"
msgid "Format"
msgstr "Format"
#: src/views/file/EditModal.vue:95
#: src/views/file/EditModal.vue:39
#, fuzzy
msgid "You have unsaved changes. Do you want to save them before closing?"
msgstr "Are you sure you want to clear?"
#: src/views/file/EditModal.vue:74
#, fuzzy
msgid "Failed to save files: %{ files }"
msgstr "Failed to calculate size"
#: src/views/file/EditModal.vue:152
#, fuzzy
msgid "File Editor"
msgstr "Website Edit"
@@ -4612,7 +4631,7 @@ msgstr ""
msgid "Are you sure you want to delete %{count} items?"
msgstr "Are you sure you want to delete the account?"
#: src/views/file/ListView.vue:823
#: src/views/file/ListView.vue:823 src/views/file/PathInput.vue:32
msgid "Path copied to clipboard"
msgstr ""
@@ -4678,20 +4697,25 @@ msgstr "Uncompress to"
msgid "Terminal - %{ path }"
msgstr "Modify permissions - %{ path }"
#: src/views/file/PathInput.vue:139
#: src/views/file/PathInput.vue:34
#, fuzzy
msgid "Failed to copy path"
msgstr "Files to compress"
#: src/views/file/PathInput.vue:150
msgid "Hide hidden files"
msgstr ""
#: src/views/file/PathInput.vue:139
#: src/views/file/PathInput.vue:150
#, fuzzy
msgid "Show hidden files"
msgstr "Show in Home"
#: src/views/file/PathInput.vue:167
#: src/views/file/PathInput.vue:184
msgid "Enter search content"
msgstr "Enter search content"
#: src/views/file/PathInput.vue:170
#: src/views/file/PathInput.vue:187
msgid "Include subdirectories"
msgstr "Include subdirectories"
@@ -5293,39 +5317,51 @@ msgstr "Update Now"
msgid "Loading update information, please wait a moment"
msgstr "Loading update information, please wait a moment"
#: src/views/log/DatabaseLog.vue:31 src/views/log/HttpLog.vue:39
#: src/views/log/OperationLog.vue:34 src/views/toolbox/SystemView.vue:235
#: src/views/log/DatabaseLog.vue:30 src/views/log/HttpLog.vue:30
#: src/views/log/OperationLog.vue:33 src/views/monitor/IndexView.vue:634
#: src/views/monitor/IndexView.vue:688 src/views/monitor/IndexView.vue:740
#: src/views/monitor/IndexView.vue:796 src/views/monitor/IndexView.vue:863
msgid "Today"
msgstr ""
#: src/views/log/DatabaseLog.vue:47 src/views/log/HttpLog.vue:55
#: src/views/log/OperationLog.vue:50 src/views/toolbox/SystemView.vue:235
msgid "Time"
msgstr "Time"
#: src/views/log/DatabaseLog.vue:40 src/views/log/OperationLog.vue:43
#: src/views/log/DatabaseLog.vue:56 src/views/log/OperationLog.vue:59
msgid "Level"
msgstr ""
#: src/views/log/DatabaseLog.vue:54
#: src/views/log/DatabaseLog.vue:70
msgid "Query"
msgstr ""
#: src/views/log/DatabaseLog.vue:64 src/views/log/HttpLog.vue:86
#: src/views/log/DatabaseLog.vue:80 src/views/log/HttpLog.vue:102
#, fuzzy
msgid "Duration"
msgstr "Direction"
#: src/views/log/DatabaseLog.vue:77
#: src/views/log/DatabaseLog.vue:93
msgid "Rows"
msgstr ""
#: src/views/log/DatabaseLog.vue:95 src/views/log/HttpLog.vue:120
#: src/views/log/OperationLog.vue:93
#: src/views/log/DatabaseLog.vue:111 src/views/log/HttpLog.vue:136
#: src/views/log/OperationLog.vue:109
msgid "Date"
msgstr "Date"
#: src/views/log/DatabaseLog.vue:118 src/views/log/HttpLog.vue:143
#: src/views/log/OperationLog.vue:116
#, fuzzy
msgid "Show entries"
msgstr "Show in Home"
#: src/views/log/HttpLog.vue:48
#: src/views/log/HttpLog.vue:64
msgid "Method"
msgstr ""
#: src/views/log/HttpLog.vue:100
#: src/views/log/HttpLog.vue:116
msgid "Client IP"
msgstr ""
@@ -5343,15 +5379,15 @@ msgstr "Database"
msgid "HTTP Log"
msgstr ""
#: src/views/log/OperationLog.vue:65
#: src/views/log/OperationLog.vue:81
msgid "Operator"
msgstr ""
#: src/views/log/OperationLog.vue:70 src/views/toolbox/IndexView.vue:24
#: src/views/log/OperationLog.vue:86 src/views/toolbox/IndexView.vue:24
msgid "System"
msgstr "System"
#: src/views/log/OperationLog.vue:76
#: src/views/log/OperationLog.vue:92
#, fuzzy
msgid "Message"
msgstr "Usage"
@@ -5446,12 +5482,6 @@ msgstr "Load"
msgid "Yesterday"
msgstr ""
#: src/views/monitor/IndexView.vue:634 src/views/monitor/IndexView.vue:688
#: src/views/monitor/IndexView.vue:740 src/views/monitor/IndexView.vue:796
#: src/views/monitor/IndexView.vue:863
msgid "Today"
msgstr ""
#: src/views/monitor/IndexView.vue:640 src/views/monitor/IndexView.vue:694
#: src/views/monitor/IndexView.vue:746 src/views/monitor/IndexView.vue:802
#: src/views/monitor/IndexView.vue:869
@@ -6336,7 +6366,7 @@ msgstr ""
msgid "Remarks"
msgstr "Remarks"
#: src/views/ssh/IndexView.vue:114
#: src/views/ssh/IndexView.vue:115
msgid "Are you sure you want to delete this host?"
msgstr "Are you sure you want to delete this host?"

View File

@@ -39,37 +39,37 @@ msgstr ""
#: src/components/common/CronPreview.vue:15
#: src/components/common/CronPreview.vue:22
#: src/components/common/CronSelector.vue:142
#: src/components/common/CronSelector.vue:163
msgid "Sunday"
msgstr ""
#: src/components/common/CronPreview.vue:16
#: src/components/common/CronSelector.vue:143
#: src/components/common/CronSelector.vue:164
msgid "Monday"
msgstr ""
#: src/components/common/CronPreview.vue:17
#: src/components/common/CronSelector.vue:144
#: src/components/common/CronSelector.vue:165
msgid "Tuesday"
msgstr ""
#: src/components/common/CronPreview.vue:18
#: src/components/common/CronSelector.vue:145
#: src/components/common/CronSelector.vue:166
msgid "Wednesday"
msgstr ""
#: src/components/common/CronPreview.vue:19
#: src/components/common/CronSelector.vue:146
#: src/components/common/CronSelector.vue:167
msgid "Thursday"
msgstr ""
#: src/components/common/CronPreview.vue:20
#: src/components/common/CronSelector.vue:147
#: src/components/common/CronSelector.vue:168
msgid "Friday"
msgstr ""
#: src/components/common/CronPreview.vue:21
#: src/components/common/CronSelector.vue:148
#: src/components/common/CronSelector.vue:169
msgid "Saturday"
msgstr ""
@@ -115,39 +115,43 @@ msgstr ""
msgid "Run every minute"
msgstr ""
#: src/components/common/CronSelector.vue:129
#: src/components/common/CronSelector.vue:149
msgid "Every Minute"
msgstr ""
#: src/components/common/CronSelector.vue:150
msgid "Every N Minutes"
msgstr ""
#: src/components/common/CronSelector.vue:130
#: src/components/common/CronSelector.vue:151
msgid "Every N Hours"
msgstr ""
#: src/components/common/CronSelector.vue:131
#: src/components/common/CronSelector.vue:152
msgid "Every N Days"
msgstr ""
#: src/components/common/CronSelector.vue:132
#: src/components/common/CronSelector.vue:153
msgid "Hourly"
msgstr ""
#: src/components/common/CronSelector.vue:133
#: src/components/common/CronSelector.vue:154
msgid "Daily"
msgstr ""
#: src/components/common/CronSelector.vue:134
#: src/components/common/CronSelector.vue:155
msgid "Weekly"
msgstr ""
#: src/components/common/CronSelector.vue:135
#: src/components/common/CronSelector.vue:156
msgid "Monthly"
msgstr ""
#: src/components/common/CronSelector.vue:136
#: src/components/common/CronSelector.vue:157
msgid "Yearly"
msgstr ""
#: src/components/common/CronSelector.vue:137
#: src/components/common/CronSelector.vue:158
#: src/views/monitor/IndexView.vue:650
#: src/views/monitor/IndexView.vue:704
#: src/views/monitor/IndexView.vue:756
@@ -160,39 +164,39 @@ msgstr ""
msgid "Custom"
msgstr ""
#: src/components/common/CronSelector.vue:153
#: src/components/common/CronSelector.vue:174
msgid "Month %{month}"
msgstr ""
#: src/components/common/CronSelector.vue:276
#: src/components/common/CronSelector.vue:301
#: src/views/apps/nginx/NginxIndex.vue:745
#: src/views/website/EditView.vue:557
msgid "Minutes"
msgstr ""
#: src/components/common/CronSelector.vue:287
#: src/components/common/CronSelector.vue:312
#: src/views/apps/nginx/NginxIndex.vue:746
#: src/views/website/EditView.vue:558
msgid "Hours"
msgstr ""
#: src/components/common/CronSelector.vue:298
#: src/components/common/CronSelector.vue:323
msgid "Days"
msgstr ""
#: src/components/common/CronSelector.vue:317
#: src/components/common/CronSelector.vue:342
msgid "Day"
msgstr ""
#: src/components/common/CronSelector.vue:336
#: src/components/common/CronSelector.vue:361
msgid "Hour"
msgstr ""
#: src/components/common/CronSelector.vue:347
#: src/components/common/CronSelector.vue:372
msgid "Minute"
msgstr ""
#: src/components/common/CronSelector.vue:354
#: src/components/common/CronSelector.vue:379
msgid "Enter Cron expression"
msgstr ""
@@ -236,6 +240,7 @@ msgstr ""
#: src/views/container/ImagePullModal.vue:198
#: src/views/container/ImageView.vue:351
#: src/views/container/ImageView.vue:366
#: src/views/file/EditModal.vue:41
#: src/views/file/ListView.vue:245
#: src/views/file/ListView.vue:738
#: src/views/file/ListView.vue:863
@@ -261,20 +266,20 @@ msgstr ""
msgid "Cancel"
msgstr ""
#: src/components/common/DraggableWindow.vue:259
#: src/components/common/DraggableWindow.vue:274
msgid "Minimize"
msgstr ""
#: src/components/common/DraggableWindow.vue:265
#: src/components/common/DraggableWindow.vue:280
#: src/views/backup/ListView.vue:78
msgid "Restore"
msgstr ""
#: src/components/common/DraggableWindow.vue:265
#: src/components/common/DraggableWindow.vue:280
msgid "Maximize"
msgstr ""
#: src/components/common/DraggableWindow.vue:270
#: src/components/common/DraggableWindow.vue:285
#: src/components/file-editor/EditorPane.vue:125
#: src/components/file-editor/EditorPane.vue:211
#: src/layout/tab/components/ContextMenu.vue:28
@@ -421,7 +426,7 @@ msgstr ""
#: src/components/common/PathSelector.vue:186
#: src/views/file/ListView.vue:1232
#: src/views/file/PathInput.vue:30
#: src/views/file/PathInput.vue:41
msgid "Invalid path"
msgstr ""
@@ -481,7 +486,7 @@ msgid "Create"
msgstr ""
#: src/components/common/PathSelector.vue:326
#: src/views/file/PathInput.vue:146
#: src/views/file/PathInput.vue:163
msgid "Root Directory"
msgstr ""
@@ -742,6 +747,7 @@ msgstr ""
#: src/components/file-editor/EditorPane.vue:123
#: src/components/file-editor/EditorToolbar.vue:98
#: src/views/file/EditModal.vue:38
msgid "Unsaved Changes"
msgstr ""
@@ -805,6 +811,7 @@ msgid "No changes to save"
msgstr ""
#: src/components/file-editor/EditorToolbar.vue:80
#: src/views/file/EditModal.vue:69
msgid "All files saved successfully"
msgstr ""
@@ -820,9 +827,9 @@ msgstr ""
#: src/components/file-editor/EditorToolbar.vue:200
#: src/components/file-editor/EditorToolbar.vue:205
#: src/components/file-editor/FileTree.vue:696
#: src/views/log/DatabaseLog.vue:108
#: src/views/log/HttpLog.vue:133
#: src/views/log/OperationLog.vue:106
#: src/views/log/DatabaseLog.vue:131
#: src/views/log/HttpLog.vue:156
#: src/views/log/OperationLog.vue:129
#: src/views/toolbox/ProcessView.vue:329
msgid "Refresh"
msgstr ""
@@ -866,6 +873,7 @@ msgstr ""
#: src/views/environment/PHPView.vue:238
#: src/views/environment/PHPView.vue:256
#: src/views/environment/PythonView.vue:97
#: src/views/file/EditModal.vue:40
#: src/views/project/EditModal.vue:575
#: src/views/setting/IndexView.vue:107
#: src/views/task/CronView.vue:284
@@ -1125,7 +1133,7 @@ msgid "Format On Type"
msgstr ""
#: src/components/file-editor/FileTree.vue:154
#: src/views/file/EditModal.vue:48
#: src/views/file/EditModal.vue:105
msgid "Failed to load file"
msgstr ""
@@ -1193,7 +1201,7 @@ msgstr ""
#: src/views/project/ListView.vue:306
#: src/views/setting/SettingUser.vue:139
#: src/views/setting/TokenModal.vue:91
#: src/views/ssh/IndexView.vue:123
#: src/views/ssh/IndexView.vue:124
#: src/views/task/CronView.vue:166
#: src/views/task/TaskView.vue:97
#: src/views/toolbox/WebHookView.vue:179
@@ -2135,7 +2143,7 @@ msgstr ""
#: src/views/database/ServerList.vue:142
#: src/views/database/UserList.vue:131
#: src/views/firewall/RuleView.vue:61
#: src/views/log/HttpLog.vue:74
#: src/views/log/HttpLog.vue:90
#: src/views/project/ListView.vue:57
#: src/views/task/TaskView.vue:22
#: src/views/toolbox/ProcessView.vue:137
@@ -2233,7 +2241,7 @@ msgstr ""
#: src/views/database/ServerList.vue:45
#: src/views/database/UserList.vue:17
#: src/views/file/PropertyModal.vue:33
#: src/views/log/OperationLog.vue:57
#: src/views/log/OperationLog.vue:73
#: src/views/project/ListView.vue:49
msgid "Type"
msgstr ""
@@ -2262,7 +2270,7 @@ msgstr ""
#: src/views/backup/StorageView.vue:419
#: src/views/backup/StorageView.vue:473
#: src/views/backup/StorageView.vue:503
#: src/views/log/HttpLog.vue:64
#: src/views/log/HttpLog.vue:80
msgid "Path"
msgstr ""
@@ -2423,7 +2431,7 @@ msgstr ""
#: src/views/file/ListView.vue:332
#: src/views/file/ListView.vue:1568
#: src/views/project/ListView.vue:179
#: src/views/ssh/IndexView.vue:105
#: src/views/ssh/IndexView.vue:106
#: src/views/task/CronView.vue:145
#: src/views/toolbox/WebHookView.vue:158
#: src/views/website/ListView.vue:200
@@ -3101,8 +3109,8 @@ msgid "Private Key"
msgstr ""
#: src/views/backup/StorageView.vue:72
#: src/views/ssh/IndexView.vue:63
#: src/views/ssh/IndexView.vue:72
#: src/views/ssh/IndexView.vue:64
#: src/views/ssh/IndexView.vue:73
msgid "Local"
msgstr ""
@@ -4604,7 +4612,15 @@ msgstr ""
msgid "Format"
msgstr ""
#: src/views/file/EditModal.vue:95
#: src/views/file/EditModal.vue:39
msgid "You have unsaved changes. Do you want to save them before closing?"
msgstr ""
#: src/views/file/EditModal.vue:74
msgid "Failed to save files: %{ files }"
msgstr ""
#: src/views/file/EditModal.vue:152
msgid "File Editor"
msgstr ""
@@ -4703,6 +4719,7 @@ msgid "Are you sure you want to delete %{count} items?"
msgstr ""
#: src/views/file/ListView.vue:823
#: src/views/file/PathInput.vue:32
msgid "Path copied to clipboard"
msgstr ""
@@ -4769,19 +4786,23 @@ msgstr ""
msgid "Terminal - %{ path }"
msgstr ""
#: src/views/file/PathInput.vue:139
#: src/views/file/PathInput.vue:34
msgid "Failed to copy path"
msgstr ""
#: src/views/file/PathInput.vue:150
msgid "Hide hidden files"
msgstr ""
#: src/views/file/PathInput.vue:139
#: src/views/file/PathInput.vue:150
msgid "Show hidden files"
msgstr ""
#: src/views/file/PathInput.vue:167
#: src/views/file/PathInput.vue:184
msgid "Enter search content"
msgstr ""
#: src/views/file/PathInput.vue:170
#: src/views/file/PathInput.vue:187
msgid "Include subdirectories"
msgstr ""
@@ -5411,42 +5432,59 @@ msgstr ""
msgid "Loading update information, please wait a moment"
msgstr ""
#: src/views/log/DatabaseLog.vue:31
#: src/views/log/HttpLog.vue:39
#: src/views/log/OperationLog.vue:34
#: src/views/log/DatabaseLog.vue:30
#: src/views/log/HttpLog.vue:30
#: src/views/log/OperationLog.vue:33
#: src/views/monitor/IndexView.vue:634
#: src/views/monitor/IndexView.vue:688
#: src/views/monitor/IndexView.vue:740
#: src/views/monitor/IndexView.vue:796
#: src/views/monitor/IndexView.vue:863
msgid "Today"
msgstr ""
#: src/views/log/DatabaseLog.vue:47
#: src/views/log/HttpLog.vue:55
#: src/views/log/OperationLog.vue:50
#: src/views/toolbox/SystemView.vue:235
msgid "Time"
msgstr ""
#: src/views/log/DatabaseLog.vue:40
#: src/views/log/OperationLog.vue:43
#: src/views/log/DatabaseLog.vue:56
#: src/views/log/OperationLog.vue:59
msgid "Level"
msgstr ""
#: src/views/log/DatabaseLog.vue:54
#: src/views/log/DatabaseLog.vue:70
msgid "Query"
msgstr ""
#: src/views/log/DatabaseLog.vue:64
#: src/views/log/HttpLog.vue:86
#: src/views/log/DatabaseLog.vue:80
#: src/views/log/HttpLog.vue:102
msgid "Duration"
msgstr ""
#: src/views/log/DatabaseLog.vue:77
#: src/views/log/DatabaseLog.vue:93
msgid "Rows"
msgstr ""
#: src/views/log/DatabaseLog.vue:95
#: src/views/log/HttpLog.vue:120
#: src/views/log/OperationLog.vue:93
#: src/views/log/DatabaseLog.vue:111
#: src/views/log/HttpLog.vue:136
#: src/views/log/OperationLog.vue:109
msgid "Date"
msgstr ""
#: src/views/log/DatabaseLog.vue:118
#: src/views/log/HttpLog.vue:143
#: src/views/log/OperationLog.vue:116
msgid "Show entries"
msgstr ""
#: src/views/log/HttpLog.vue:48
#: src/views/log/HttpLog.vue:64
msgid "Method"
msgstr ""
#: src/views/log/HttpLog.vue:100
#: src/views/log/HttpLog.vue:116
msgid "Client IP"
msgstr ""
@@ -5462,16 +5500,16 @@ msgstr ""
msgid "HTTP Log"
msgstr ""
#: src/views/log/OperationLog.vue:65
#: src/views/log/OperationLog.vue:81
msgid "Operator"
msgstr ""
#: src/views/log/OperationLog.vue:70
#: src/views/log/OperationLog.vue:86
#: src/views/toolbox/IndexView.vue:24
msgid "System"
msgstr ""
#: src/views/log/OperationLog.vue:76
#: src/views/log/OperationLog.vue:92
msgid "Message"
msgstr ""
@@ -5565,14 +5603,6 @@ msgstr ""
msgid "Yesterday"
msgstr ""
#: src/views/monitor/IndexView.vue:634
#: src/views/monitor/IndexView.vue:688
#: src/views/monitor/IndexView.vue:740
#: src/views/monitor/IndexView.vue:796
#: src/views/monitor/IndexView.vue:863
msgid "Today"
msgstr ""
#: src/views/monitor/IndexView.vue:640
#: src/views/monitor/IndexView.vue:694
#: src/views/monitor/IndexView.vue:746
@@ -6375,7 +6405,7 @@ msgstr ""
msgid "Remarks"
msgstr ""
#: src/views/ssh/IndexView.vue:114
#: src/views/ssh/IndexView.vue:115
msgid "Are you sure you want to delete this host?"
msgstr ""

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -20,8 +20,24 @@ interface LogEntry {
// 数据加载
const limit = ref(200)
const selectedDate = ref<string | null>(null)
// 获取可用的日志日期列表
const { data: dates } = useRequest(() => log.dates('db'), { initialData: [] })
// 日期选项
const dateOptions = computed(() => {
const options = [{ label: $gettext('Today'), value: '' }]
if (dates.value) {
for (const date of dates.value) {
options.push({ label: date, value: date })
}
}
return options
})
const { loading, data, send: refresh } = useRequest(
() => log.list('db', limit.value),
() => log.list('db', limit.value, selectedDate.value || ''),
{ initialData: [] }
)
@@ -92,6 +108,13 @@ const handleRefresh = () => {
<template>
<div class="flex flex-col h-full">
<div class="mb-4 flex gap-4 items-center">
<span>{{ $gettext('Date') }}:</span>
<n-select
v-model:value="selectedDate"
:options="dateOptions"
class="w-150px"
@update:value="handleRefresh"
/>
<span>{{ $gettext('Show entries') }}:</span>
<n-select
v-model:value="limit"

View File

@@ -20,8 +20,24 @@ interface LogEntry {
// 数据加载
const limit = ref(200)
const selectedDate = ref<string | null>(null)
// 获取可用的日志日期列表
const { data: dates } = useRequest(() => log.dates('http'), { initialData: [] })
// 日期选项
const dateOptions = computed(() => {
const options = [{ label: $gettext('Today'), value: '' }]
if (dates.value) {
for (const date of dates.value) {
options.push({ label: date, value: date })
}
}
return options
})
const { loading, data, send: refresh } = useRequest(
() => log.list('http', limit.value),
() => log.list('http', limit.value, selectedDate.value || ''),
{ initialData: [] }
)
@@ -117,6 +133,13 @@ const handleRefresh = () => {
<template>
<div class="flex flex-col h-full">
<div class="mb-4 flex gap-4 items-center">
<span>{{ $gettext('Date') }}:</span>
<n-select
v-model:value="selectedDate"
:options="dateOptions"
class="w-150px"
@update:value="handleRefresh"
/>
<span>{{ $gettext('Show entries') }}:</span>
<n-select
v-model:value="limit"

View File

@@ -23,8 +23,24 @@ interface LogEntry {
// 数据加载
const limit = ref(200)
const selectedDate = ref<string | null>(null)
// 获取可用的日志日期列表
const { data: dates } = useRequest(() => log.dates('app'), { initialData: [] })
// 日期选项
const dateOptions = computed(() => {
const options = [{ label: $gettext('Today'), value: '' }]
if (dates.value) {
for (const date of dates.value) {
options.push({ label: date, value: date })
}
}
return options
})
const { loading, data, send: refresh } = useRequest(
() => log.list('app', limit.value),
() => log.list('app', limit.value, selectedDate.value || ''),
{ initialData: [] }
)
@@ -90,6 +106,13 @@ const handleRefresh = () => {
<template>
<div class="flex flex-col h-full">
<div class="mb-4 flex gap-4 items-center">
<span>{{ $gettext('Date') }}:</span>
<n-select
v-model:value="selectedDate"
:options="dateOptions"
class="w-150px"
@update:value="handleRefresh"
/>
<span>{{ $gettext('Show entries') }}:</span>
<n-select
v-model:value="limit"