feat: Cache List Page Filter Conditions (#13314)

This commit is contained in:
CityFun
2026-07-21 15:39:46 +08:00
committed by GitHub
parent 092b57413b
commit b347abe100
24 changed files with 457 additions and 165 deletions
+139
View File
@@ -0,0 +1,139 @@
package service
import (
"encoding/json"
"strings"
"github.com/1Panel-dev/1Panel/agent/utils/common"
)
const (
vllmAppKeyForUpgrade = "vllm"
vllmImageEnvKey = "IMAGE"
vllmImageTypeNvidia = "nvidia"
vllmImageTypeIntel = "intel"
vllmImageTypeAscend = "ascend"
)
func resolveVllmVersionFamily(version, image string) string {
normalizedVersion := strings.ToLower(strings.TrimSpace(version))
if strings.HasPrefix(normalizedVersion, vllmImageTypeIntel+"-") {
return vllmImageTypeIntel
}
if strings.HasPrefix(normalizedVersion, vllmImageTypeAscend+"-") {
return vllmImageTypeAscend
}
if strings.HasPrefix(normalizedVersion, vllmImageTypeNvidia+"-") {
return vllmImageTypeNvidia
}
normalizedImage := strings.ToLower(strings.TrimSpace(image))
if strings.Contains(normalizedImage, "intel/") || strings.Contains(normalizedImage, "llm-scaler-vllm") {
return vllmImageTypeIntel
}
if strings.Contains(normalizedImage, "ascend/") || strings.Contains(normalizedImage, "vllm-ascend") {
return vllmImageTypeAscend
}
return vllmImageTypeNvidia
}
func trimVllmVersionFamily(version string) string {
trimmed := strings.TrimSpace(version)
normalized := strings.ToLower(trimmed)
for _, family := range []string{vllmImageTypeNvidia, vllmImageTypeIntel, vllmImageTypeAscend} {
prefix := family + "-"
if strings.HasPrefix(normalized, prefix) {
return strings.TrimSpace(trimmed[len(prefix):])
}
}
return trimmed
}
func buildDefaultVllmImageByVersion(version string) string {
tag := trimVllmVersionFamily(version)
family := resolveVllmVersionFamily(version, "")
if family == vllmImageTypeIntel {
return "intel/llm-scaler-vllm:" + tag
}
if tag != "" && !strings.HasPrefix(strings.ToLower(tag), "v") {
tag = "v" + tag
}
if family == vllmImageTypeAscend {
return "quay.io/ascend/vllm-ascend:" + tag
}
return "vllm/vllm-openai:" + tag
}
func isVllmUpgradeVersionAllowed(currentVersion, targetVersion, currentImage string) bool {
currentFamily := resolveVllmVersionFamily(currentVersion, currentImage)
targetFamily := resolveVllmVersionFamily(targetVersion, "")
return currentFamily == targetFamily
}
func hasVllmVersionFamilyPrefix(version string) bool {
normalized := strings.ToLower(strings.TrimSpace(version))
return strings.HasPrefix(normalized, vllmImageTypeNvidia+"-") ||
strings.HasPrefix(normalized, vllmImageTypeIntel+"-") ||
strings.HasPrefix(normalized, vllmImageTypeAscend+"-")
}
func isVllmUpgradeCandidate(currentVersion, targetVersion, currentImage string) bool {
if strings.TrimSpace(currentVersion) == strings.TrimSpace(targetVersion) {
return false
}
if !isVllmUpgradeVersionAllowed(currentVersion, targetVersion, currentImage) {
return false
}
if common.CompareVersion(targetVersion, currentVersion) {
return true
}
return !hasVllmVersionFamilyPrefix(currentVersion) &&
resolveVllmVersionFamily(targetVersion, "") == vllmImageTypeNvidia &&
trimVllmVersionFamily(currentVersion) == trimVllmVersionFamily(targetVersion)
}
func buildVllmUpgradeImage(currentImage, currentVersion, targetVersion string) string {
trimmedImage := strings.TrimSpace(currentImage)
if trimmedImage == "" || trimmedImage == buildDefaultVllmImageByVersion(currentVersion) {
return buildDefaultVllmImageByVersion(targetVersion)
}
return trimmedImage
}
func loadVllmImageFromEnv(raw string) string {
envs := make(map[string]interface{})
if strings.TrimSpace(raw) == "" {
return ""
}
if err := json.Unmarshal([]byte(raw), &envs); err != nil {
return ""
}
if image, ok := envs[vllmImageEnvKey].(string); ok {
return strings.TrimSpace(image)
}
return ""
}
func setVllmImageInEnvContent(content []byte, image string) []byte {
normalizedImage := strings.TrimSpace(image)
if normalizedImage == "" {
return content
}
lines := strings.Split(string(content), "\n")
replaced := false
for index, line := range lines {
if strings.HasPrefix(line, vllmImageEnvKey+"=") {
lines[index] = vllmImageEnvKey + "=" + normalizedImage
replaced = true
break
}
}
if !replaced {
if len(lines) > 0 && lines[len(lines)-1] == "" {
lines[len(lines)-1] = vllmImageEnvKey + "=" + normalizedImage
lines = append(lines, "")
} else {
lines = append(lines, vllmImageEnvKey+"="+normalizedImage)
}
}
return []byte(strings.Join(lines, "\n"))
}
+6 -7
View File
@@ -8,7 +8,7 @@ require (
github.com/aliyun/aliyun-oss-go-sdk v3.0.2+incompatible
github.com/compose-spec/compose-go/v2 v2.13.0
github.com/creack/pty v1.1.24
github.com/docker/cli v29.6.1+incompatible
github.com/docker/cli v29.6.2+incompatible
github.com/docker/docker v28.5.2+incompatible
github.com/docker/go-connections v0.7.0
github.com/fsnotify/fsnotify v1.10.1
@@ -36,8 +36,8 @@ require (
github.com/oschwald/maxminddb-golang v1.13.1
github.com/patrickmn/go-cache v2.1.0+incompatible
github.com/pkg/errors v0.9.1
github.com/pkg/sftp v1.13.10
github.com/qiniu/go-sdk/v7 v7.26.15
github.com/pkg/sftp v1.13.11
github.com/qiniu/go-sdk/v7 v7.26.16
github.com/robfig/cron/v3 v3.0.1
github.com/shirou/gopsutil/v4 v4.26.6
github.com/sirupsen/logrus v1.9.4
@@ -50,10 +50,10 @@ require (
github.com/tomasen/fcgi_client v0.0.0-20180423082037-2bb3d819fd19
github.com/upyun/go-sdk v2.1.0+incompatible
go.mongodb.org/mongo-driver/v2 v2.8.0
golang.org/x/crypto v0.53.0
golang.org/x/net v0.56.0
golang.org/x/crypto v0.54.0
golang.org/x/net v0.57.0
golang.org/x/sync v0.22.0
golang.org/x/sys v0.46.0
golang.org/x/sys v0.47.0
golang.org/x/text v0.40.0
golang.org/x/time v0.15.0
google.golang.org/genproto v0.0.0-20260414002931-afd174a4e478
@@ -113,7 +113,6 @@ require (
github.com/ebitengine/purego v0.10.0 // indirect
github.com/felixge/httpsnoop v1.0.4 // indirect
github.com/gabriel-vasile/mimetype v1.4.13 // indirect
github.com/gammazero/toposort v0.1.1 // indirect
github.com/gin-contrib/sse v1.1.1 // indirect
github.com/glebarez/go-sqlite v1.22.0 // indirect
github.com/go-acme/alidns-20150109/v5 v5.4.1 // indirect
+14 -16
View File
@@ -225,8 +225,8 @@ github.com/distribution/reference v0.6.0 h1:0IXCQ5g4/QMHHkarYzh5l+u8T3t73zM5Qvfr
github.com/distribution/reference v0.6.0/go.mod h1:BbU0aIcezP1/5jX/8MP0YiH4SdvB5Y4f/wlDRiLyi3E=
github.com/dlclark/regexp2 v1.12.0 h1:0j4c5qQmnC6XOWNjP3PIXURXN2gWx76rd3KvgdPkCz8=
github.com/dlclark/regexp2 v1.12.0/go.mod h1:DHkYz0B9wPfa6wondMfaivmHpzrQ3v9q8cnmRbL6yW8=
github.com/docker/cli v29.6.1+incompatible h1:oO7F4nn3Ovr/5TlfTUWFbMwBSS/B7Xs6Epv26gBrUP8=
github.com/docker/cli v29.6.1+incompatible/go.mod h1:JLrzqnKDaYBop7H2jaqPtU4hHvMKP+vjCwu2uszcLI8=
github.com/docker/cli v29.6.2+incompatible h1:/bjePvcbbFTnRrMfWJBY7AjfICdsiLVgHn6LwTVOcqw=
github.com/docker/cli v29.6.2+incompatible/go.mod h1:JLrzqnKDaYBop7H2jaqPtU4hHvMKP+vjCwu2uszcLI8=
github.com/docker/docker v28.5.2+incompatible h1:DBX0Y0zAjZbSrm1uzOkdr1onVghKaftjlSWt4AFexzM=
github.com/docker/docker v28.5.2+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk=
github.com/docker/docker-credential-helpers v0.9.5 h1:EFNN8DHvaiK8zVqFA2DT6BjXE0GzfLOZ38ggPTKePkY=
@@ -274,8 +274,6 @@ github.com/fsnotify/fsnotify v1.10.1 h1:b0/UzAf9yR5rhf3RPm9gf3ehBPpf0oZKIjtpKrx5
github.com/fsnotify/fsnotify v1.10.1/go.mod h1:TLheqan6HD6GBK6PrDWyDPBaEV8LspOxvPSjC+bVfgo=
github.com/gabriel-vasile/mimetype v1.4.13 h1:46nXokslUBsAJE/wMsp5gtO500a4F3Nkz9Ufpk2AcUM=
github.com/gabriel-vasile/mimetype v1.4.13/go.mod h1:d+9Oxyo1wTzWdyVUPMmXFvp4F9tea18J8ufA774AB3s=
github.com/gammazero/toposort v0.1.1 h1:OivGxsWxF3U3+U80VoLJ+f50HcPU1MIqE1JlKzoJ2Eg=
github.com/gammazero/toposort v0.1.1/go.mod h1:H2cozTnNpMw0hg2VHAYsAxmkHXBYroNangj2NTBQDvw=
github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04=
github.com/gin-contrib/sse v1.1.1 h1:uGYpNwTacv5R68bSGMapo62iLTRa9l5zxGCps4hK6ko=
github.com/gin-contrib/sse v1.1.1/go.mod h1:QXzuVkA0YO7o/gun03UI1Q+FTI8ZV/n5t03kIQAI89s=
@@ -696,8 +694,8 @@ github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINE
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pkg/profile v1.2.1/go.mod h1:hJw3o1OdXxsrSjjVksARp5W95eeEaEfptyVZyv6JUPA=
github.com/pkg/sftp v1.13.10 h1:+5FbKNTe5Z9aspU88DPIKJ9z2KZoaGCu6Sr6kKR/5mU=
github.com/pkg/sftp v1.13.10/go.mod h1:bJ1a7uDhrX/4OII+agvy28lzRvQrmIQuaHrcI1HbeGA=
github.com/pkg/sftp v1.13.11 h1:0N92SLTB8JqASJB14ZLHHzFnBV8mG9zw4K7jghEFWuE=
github.com/pkg/sftp v1.13.11/go.mod h1:uNkH9roSXglNJqM+glJJi+TQXQUm0fXFWqCFmT8hsN0=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 h1:Jamvg5psRIccs7FGNTlIRMkT8wgtp5eCXdBlqhYGL6U=
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
@@ -725,8 +723,8 @@ github.com/prometheus/procfs v0.0.8/go.mod h1:7Qr8sr6344vo1JqZ6HhLceV9o3AJ1Ff+Gx
github.com/prometheus/procfs v0.1.3/go.mod h1:lV6e/gmhEcM9IjHGsFOCxxuZ+z1YqCvr4OA4YeYWdaU=
github.com/prometheus/procfs v0.6.0/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1xBZuNvfVA=
github.com/prometheus/procfs v0.7.3/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1xBZuNvfVA=
github.com/qiniu/go-sdk/v7 v7.26.15 h1:CaKVcP29ZnOp/pqE7U3RAZxqwL7CmtMTWlV1gAV71H0=
github.com/qiniu/go-sdk/v7 v7.26.15/go.mod h1:ri7fGwbio0pRDFr8EK5TUpx0DbnpIMJ2bMSDxGWfCbk=
github.com/qiniu/go-sdk/v7 v7.26.16 h1:WzPUb0XdBgWnjV8n9revG13vTUcUO4LMcWoacMneH2M=
github.com/qiniu/go-sdk/v7 v7.26.16/go.mod h1:pTwVR1B+8SXcPLhDzBUasiKFTD9F7jRglRDR553BW3k=
github.com/quic-go/qpack v0.6.0 h1:g7W+BMYynC1LbYLSqRt8PBg5Tgwxn214ZZR34VIOjz8=
github.com/quic-go/qpack v0.6.0/go.mod h1:lUpLKChi8njB4ty2bFLX2x4gzDqXwUpaO1DP9qMDZII=
github.com/quic-go/quic-go v0.59.0 h1:OLJkp1Mlm/aS7dpKgTc6cnpynnD2Xg7C1pwL6vy/SAw=
@@ -950,8 +948,8 @@ golang.org/x/crypto v0.19.0/go.mod h1:Iy9bg/ha4yyC70EfRS8jz+B6ybOBKMaSxLj6P6oBDf
golang.org/x/crypto v0.21.0/go.mod h1:0BP7YvVV9gBbVKyeTG0Gyn+gZm94bibOW5BjDEYAOMs=
golang.org/x/crypto v0.23.0/go.mod h1:CKFgDieR+mRhux2Lsu27y0fO304Db0wZe70UKqHu0v8=
golang.org/x/crypto v0.24.0/go.mod h1:Z1PMYSOR5nyMcyAVAIQSKCDwalqy85Aqn1x3Ws4L5DM=
golang.org/x/crypto v0.53.0 h1:QZ4Muo8THX6CizN2vPPd5fBGHyogrdK9fG4wLPFUsto=
golang.org/x/crypto v0.53.0/go.mod h1:DNLU434OwVakk9PzuwV8w62mAJpRJL3vsgcfp4Qnsio=
golang.org/x/crypto v0.54.0 h1:YLIA59K4fiNzHzjnZt2tUJQjQtUWfWbeHBqKtk3eScw=
golang.org/x/crypto v0.54.0/go.mod h1:KWL8ny2AZdGR2cWmzeHrp2azQPGogOv+HeQaVEXC2dk=
golang.org/x/exp v0.0.0-20180321215751-8460e604b9de/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
golang.org/x/exp v0.0.0-20180807140117-3d87b88a115f/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
@@ -1049,8 +1047,8 @@ golang.org/x/net v0.21.0/go.mod h1:bIjVDfnllIU7BJ2DNgfnXvpSvtn8VRwhlsaeUTyUS44=
golang.org/x/net v0.23.0/go.mod h1:JKghWKKOSdJwpW2GEx0Ja7fmaKnMsbu+MWVZTokSYmg=
golang.org/x/net v0.25.0/go.mod h1:JkAGAh7GEvH74S6FOH42FLoXpXbE/aqXSrIQjXgsiwM=
golang.org/x/net v0.26.0/go.mod h1:5YKkiSynbBIh3p6iOc/vibscux0x38BZDkn8sCUPxHE=
golang.org/x/net v0.56.0 h1:Rw8j/hFzGvJUZwNBXnAtf5sVDVt+65SK2C7IxCxZt5o=
golang.org/x/net v0.56.0/go.mod h1:D3Ku6r+V6JROoZK144D2XfMHFcMq/0zSfLelVTCFKec=
golang.org/x/net v0.57.0 h1:K5+3DljvIuDG9/Jv9rvyMywYNFCQ9RSUY6OOTTkT+tE=
golang.org/x/net v0.57.0/go.mod h1:KpXc8iv+r3XplLAG/f7Jsf9RPszJzdR0f58q9vGOuEU=
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
@@ -1152,8 +1150,8 @@ golang.org/x/sys v0.17.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/sys v0.18.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/sys v0.20.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/sys v0.21.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/sys v0.46.0 h1:noSf2Fq6F8DBgS+LysIkx7rIExoNHJsxOAtPp4rthXw=
golang.org/x/sys v0.46.0/go.mod h1:4GL1E5IUh+htKOUEOaiffhrAeqysfVGipDYzABqnCmw=
golang.org/x/sys v0.47.0 h1:o7XGOvZQCADBQQ4Y7VNq2dRWQR7JmOUW8Kxx4ZsNgWs=
golang.org/x/sys v0.47.0/go.mod h1:4GL1E5IUh+htKOUEOaiffhrAeqysfVGipDYzABqnCmw=
golang.org/x/telemetry v0.0.0-20240228155512-f48c80bd79b2/go.mod h1:TeRTkGYfJXctD9OcfyVLyj2J3IxLnKwHJR8f4D8a3YE=
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
@@ -1167,8 +1165,8 @@ golang.org/x/term v0.17.0/go.mod h1:lLRBjIVuehSbZlaOtGMbcMncT+aqLLLmKrsjNrUguwk=
golang.org/x/term v0.18.0/go.mod h1:ILwASektA3OnRv7amZ1xhE/KTR+u50pbXfZ03+6Nx58=
golang.org/x/term v0.20.0/go.mod h1:8UkIAJTvZgivsXaD6/pH6U9ecQzZ45awqEOzuCvwpFY=
golang.org/x/term v0.21.0/go.mod h1:ooXLefLobQVslOqselCNF4SxFAaoS6KujMbsGzSDmX0=
golang.org/x/term v0.44.0 h1:0rLvDRCtNj0gZkyIXhCyOb2OAzEhLVqc4B+hrsBhrmc=
golang.org/x/term v0.44.0/go.mod h1:7ze4MdzUzLXpSAoFP1H0bOI9aXDqveSvatT5vKcFh2Y=
golang.org/x/term v0.45.0 h1:NwWyBmoJCbfTHpxrWoZ9C6/VxOf7ic219I8xZZFdrf0=
golang.org/x/term v0.45.0/go.mod h1:9aqxs0blBcrm/n0L9QW0aRVD+ktan8ssZromtqJC43w=
golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
+5 -5
View File
@@ -21,7 +21,7 @@ require (
github.com/oschwald/maxminddb-golang v1.13.1
github.com/patrickmn/go-cache v2.1.0+incompatible
github.com/pkg/errors v0.9.1
github.com/pkg/sftp v1.13.10
github.com/pkg/sftp v1.13.11
github.com/robfig/cron/v3 v3.0.1
github.com/shirou/gopsutil/v4 v4.26.6
github.com/sirupsen/logrus v1.9.4
@@ -32,10 +32,10 @@ require (
github.com/swaggo/files/v2 v2.0.2
github.com/swaggo/swag v1.16.6
github.com/xlzd/gotp v0.1.0
golang.org/x/crypto v0.53.0
golang.org/x/net v0.56.0
golang.org/x/sys v0.46.0
golang.org/x/term v0.44.0
golang.org/x/crypto v0.54.0
golang.org/x/net v0.57.0
golang.org/x/sys v0.47.0
golang.org/x/term v0.45.0
golang.org/x/text v0.40.0
gopkg.in/yaml.v2 v2.4.0
gopkg.in/yaml.v3 v3.0.1
+10 -10
View File
@@ -182,8 +182,8 @@ github.com/phpdave11/gofpdi v1.0.15/go.mod h1:vBmVV0Do6hSBHC8uKUQ71JGW+ZGQq74llk
github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pkg/sftp v1.13.10 h1:+5FbKNTe5Z9aspU88DPIKJ9z2KZoaGCu6Sr6kKR/5mU=
github.com/pkg/sftp v1.13.10/go.mod h1:bJ1a7uDhrX/4OII+agvy28lzRvQrmIQuaHrcI1HbeGA=
github.com/pkg/sftp v1.13.11 h1:0N92SLTB8JqASJB14ZLHHzFnBV8mG9zw4K7jghEFWuE=
github.com/pkg/sftp v1.13.11/go.mod h1:uNkH9roSXglNJqM+glJJi+TQXQUm0fXFWqCFmT8hsN0=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/power-devops/perfstat v0.0.0-20240221224432-82ca36839d55 h1:o4JXh1EVt9k/+g42oCprj/FisM4qX9L3sZB3upGN2ZU=
@@ -267,8 +267,8 @@ golang.org/x/arch v0.26.0 h1:jZ6dpec5haP/fUv1kLCbuJy6dnRrfX6iVK08lZBFpk4=
golang.org/x/arch v0.26.0/go.mod h1:0X+GdSIP+kL5wPmpK7sdkEVTt2XoYP0cSjQSbZBwOi8=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/crypto v0.53.0 h1:QZ4Muo8THX6CizN2vPPd5fBGHyogrdK9fG4wLPFUsto=
golang.org/x/crypto v0.53.0/go.mod h1:DNLU434OwVakk9PzuwV8w62mAJpRJL3vsgcfp4Qnsio=
golang.org/x/crypto v0.54.0 h1:YLIA59K4fiNzHzjnZt2tUJQjQtUWfWbeHBqKtk3eScw=
golang.org/x/crypto v0.54.0/go.mod h1:KWL8ny2AZdGR2cWmzeHrp2azQPGogOv+HeQaVEXC2dk=
golang.org/x/image v0.0.0-20190910094157-69e4b8554b2a/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0=
golang.org/x/image v0.39.0 h1:skVYidAEVKgn8lZ602XO75asgXBgLj9G/FE3RbuPFww=
golang.org/x/image v0.39.0/go.mod h1:sIbmppfU+xFLPIG0FoVUTvyBMmgng1/XAMhQ2ft0hpA=
@@ -276,8 +276,8 @@ golang.org/x/mod v0.37.0 h1:vF1DjpVEshcIqoEaauuHebaLk1O1forxjxBaVn884JQ=
golang.org/x/mod v0.37.0/go.mod h1:m8S8VeM9r4dzDwjrKO0a1sZP3YjeMamRRlD+fmR2Q/0=
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20201202161906-c7110b5ffcbb/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
golang.org/x/net v0.56.0 h1:Rw8j/hFzGvJUZwNBXnAtf5sVDVt+65SK2C7IxCxZt5o=
golang.org/x/net v0.56.0/go.mod h1:D3Ku6r+V6JROoZK144D2XfMHFcMq/0zSfLelVTCFKec=
golang.org/x/net v0.57.0 h1:K5+3DljvIuDG9/Jv9rvyMywYNFCQ9RSUY6OOTTkT+tE=
golang.org/x/net v0.57.0/go.mod h1:KpXc8iv+r3XplLAG/f7Jsf9RPszJzdR0f58q9vGOuEU=
golang.org/x/sync v0.22.0 h1:SZjpbeLmrCk4xhRSZFNZW5gFUeCeFgjekvI/+gfScek=
golang.org/x/sync v0.22.0/go.mod h1:9xrNwdLfx4jkKbNva9FpL6vEN7evnE43NNNJQ2LF3+0=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
@@ -285,10 +285,10 @@ golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7w
golang.org/x/sys v0.0.0-20190916202348-b4ddaad3f8a3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20201204225414-ed752295db88/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.46.0 h1:noSf2Fq6F8DBgS+LysIkx7rIExoNHJsxOAtPp4rthXw=
golang.org/x/sys v0.46.0/go.mod h1:4GL1E5IUh+htKOUEOaiffhrAeqysfVGipDYzABqnCmw=
golang.org/x/term v0.44.0 h1:0rLvDRCtNj0gZkyIXhCyOb2OAzEhLVqc4B+hrsBhrmc=
golang.org/x/term v0.44.0/go.mod h1:7ze4MdzUzLXpSAoFP1H0bOI9aXDqveSvatT5vKcFh2Y=
golang.org/x/sys v0.47.0 h1:o7XGOvZQCADBQQ4Y7VNq2dRWQR7JmOUW8Kxx4ZsNgWs=
golang.org/x/sys v0.47.0/go.mod h1:4GL1E5IUh+htKOUEOaiffhrAeqysfVGipDYzABqnCmw=
golang.org/x/term v0.45.0 h1:NwWyBmoJCbfTHpxrWoZ9C6/VxOf7ic219I8xZZFdrf0=
golang.org/x/term v0.45.0/go.mod h1:9aqxs0blBcrm/n0L9QW0aRVD+ktan8ssZromtqJC43w=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.40.0 h1:Ub2Z6/xjgF1WrYQz2nuITOEegKFtiIy+rieRJ5lHZKs=
+89 -89
View File
@@ -52,12 +52,12 @@
"@tailwindcss/postcss": "^4.3.0",
"@types/node": "^26.1.1",
"@types/uuid": "^11.0.0",
"@typescript-eslint/eslint-plugin": "^8.63.0",
"@typescript-eslint/parser": "^8.63.0",
"@typescript-eslint/eslint-plugin": "^8.64.0",
"@typescript-eslint/parser": "^8.64.0",
"@vitejs/plugin-vue": "^6.0.7",
"@vitejs/plugin-vue-jsx": "^5.1.6",
"@vue/compiler-sfc": "^3.5.35",
"autoprefixer": "^10.5.0",
"autoprefixer": "^10.5.4",
"esbuild": "^0.28.1",
"eslint": "^10.6.0",
"eslint-config-prettier": "^10.1.8",
@@ -66,9 +66,9 @@
"lint-staged": "^17.0.7",
"postcss": "^8.5.14",
"postcss-html": "^1.8.1",
"prettier": "^3.8.2",
"prettier": "^3.9.5",
"rollup-plugin-visualizer": "^5.5.4",
"sass": "^1.100.0",
"sass": "^1.101.0",
"standard-version": "^9.5.0",
"tailwindcss": "^4.3.0",
"typescript": "^6.0.3",
@@ -3057,17 +3057,17 @@
"license": "MIT"
},
"node_modules/@typescript-eslint/eslint-plugin": {
"version": "8.63.0",
"resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.63.0.tgz",
"integrity": "sha512-rvwSgqT+DHpWdzfSzPatRLm02a0GlESt++9iy3hLCDY4BgkaLcl8LBi9Yh7XGFBpwcBE/K3024QuXWTpbz4FfQ==",
"version": "8.64.0",
"resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.64.0.tgz",
"integrity": "sha512-CGvQPBxN3wZLu6Rz2kFUpZeoCm78xUic92ck39KPePkO1NPOwjCqdQnm5Q87tpWw9vcBvW8XLrDXjH9PWYtJ3Q==",
"dev": true,
"license": "MIT",
"dependencies": {
"@eslint-community/regexpp": "^4.12.2",
"@typescript-eslint/scope-manager": "8.63.0",
"@typescript-eslint/type-utils": "8.63.0",
"@typescript-eslint/utils": "8.63.0",
"@typescript-eslint/visitor-keys": "8.63.0",
"@typescript-eslint/scope-manager": "8.64.0",
"@typescript-eslint/type-utils": "8.64.0",
"@typescript-eslint/utils": "8.64.0",
"@typescript-eslint/visitor-keys": "8.64.0",
"ignore": "^7.0.5",
"natural-compare": "^1.4.0",
"ts-api-utils": "^2.5.0"
@@ -3080,7 +3080,7 @@
"url": "https://opencollective.com/typescript-eslint"
},
"peerDependencies": {
"@typescript-eslint/parser": "^8.63.0",
"@typescript-eslint/parser": "^8.64.0",
"eslint": "^8.57.0 || ^9.0.0 || ^10.0.0",
"typescript": ">=4.8.4 <6.1.0"
}
@@ -3096,17 +3096,17 @@
}
},
"node_modules/@typescript-eslint/parser": {
"version": "8.63.0",
"resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.63.0.tgz",
"integrity": "sha512-gwh4gvvlaVDKKxyfxMG+Gnu1u9X0OQBwyGLkbwB65dIzBKnxeRiJlNFqlI3zwVhNXJIs6qV7mlFCn/BIajlVig==",
"version": "8.64.0",
"resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.64.0.tgz",
"integrity": "sha512-KA0OshtlcCCXmbfqyZkM5pV3/WNraJf7DkJRLpyrmwPtud57H5BDX7C3k0LPSPxpprfRL+cJDGabF10mvNCoCw==",
"dev": true,
"license": "MIT",
"peer": true,
"dependencies": {
"@typescript-eslint/scope-manager": "8.63.0",
"@typescript-eslint/types": "8.63.0",
"@typescript-eslint/typescript-estree": "8.63.0",
"@typescript-eslint/visitor-keys": "8.63.0",
"@typescript-eslint/scope-manager": "8.64.0",
"@typescript-eslint/types": "8.64.0",
"@typescript-eslint/typescript-estree": "8.64.0",
"@typescript-eslint/visitor-keys": "8.64.0",
"debug": "^4.4.3"
},
"engines": {
@@ -3122,14 +3122,14 @@
}
},
"node_modules/@typescript-eslint/project-service": {
"version": "8.63.0",
"resolved": "https://registry.npmjs.org/@typescript-eslint/project-service/-/project-service-8.63.0.tgz",
"integrity": "sha512-e5dh0/UI0ok53AlZ5wRkXCB32z/f2jUZqPR/ygAw5WYaSw8j9EoJWlS7wQjr/dmOaqWjnPIn2m+HhVPCMWGZVQ==",
"version": "8.64.0",
"resolved": "https://registry.npmjs.org/@typescript-eslint/project-service/-/project-service-8.64.0.tgz",
"integrity": "sha512-tk4WpOJ6IEbGrVHaNmM0YRrwAD3exZlIK3iadQNAxh4YKk6jvUQ4ecq18n+v7+meh+cJ3j+D8nbk8sRKhlwLQg==",
"dev": true,
"license": "MIT",
"dependencies": {
"@typescript-eslint/tsconfig-utils": "^8.63.0",
"@typescript-eslint/types": "^8.63.0",
"@typescript-eslint/tsconfig-utils": "^8.64.0",
"@typescript-eslint/types": "^8.64.0",
"debug": "^4.4.3"
},
"engines": {
@@ -3144,14 +3144,14 @@
}
},
"node_modules/@typescript-eslint/scope-manager": {
"version": "8.63.0",
"resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.63.0.tgz",
"integrity": "sha512-uUyfMWCnDSN8bCpcrY8nGP2BLkQ9Xn0GsipcONcpIDWhwhO4ZSyHvyS14U3X75mzxWxL3I2UZIrenTzdzcJO8A==",
"version": "8.64.0",
"resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.64.0.tgz",
"integrity": "sha512-CXEaFdYXjSTgKhisNkwCcJwTP8Pl+fmRrEQrri4nm3vU743bALrxzLmq7fHG/7e6a5xO0lDYeURpZmBuhHk54w==",
"dev": true,
"license": "MIT",
"dependencies": {
"@typescript-eslint/types": "8.63.0",
"@typescript-eslint/visitor-keys": "8.63.0"
"@typescript-eslint/types": "8.64.0",
"@typescript-eslint/visitor-keys": "8.64.0"
},
"engines": {
"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
@@ -3162,9 +3162,9 @@
}
},
"node_modules/@typescript-eslint/tsconfig-utils": {
"version": "8.63.0",
"resolved": "https://registry.npmjs.org/@typescript-eslint/tsconfig-utils/-/tsconfig-utils-8.63.0.tgz",
"integrity": "sha512-sUAbkulqBAsncKnbRP3+7CtQFRKicexnj7ZwNC6ddCR7EmrXvjvdCYMJbUIqMd6lwoEriZjwLo08aS5tSjVMHg==",
"version": "8.64.0",
"resolved": "https://registry.npmjs.org/@typescript-eslint/tsconfig-utils/-/tsconfig-utils-8.64.0.tgz",
"integrity": "sha512-2yo8rRNKuzbVWQp5kslhANqZ2uDAeROQHBRZNPu8JDsHmeFNj/XJJhX/FhNUWmkHHvoNsKa6+tHJiig87EzsQw==",
"dev": true,
"license": "MIT",
"engines": {
@@ -3179,15 +3179,15 @@
}
},
"node_modules/@typescript-eslint/type-utils": {
"version": "8.63.0",
"resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.63.0.tgz",
"integrity": "sha512-Nzzh/OGxVCOjObjaj1CQF2RUasyYy2Jfuh+zZ3PjLzG2fYRriAiZLib9UKtO+CpQAS3YHiAS+ckZDclwqI1TPA==",
"version": "8.64.0",
"resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.64.0.tgz",
"integrity": "sha512-XWG4Fmmv/6SvyS9nH8jWrKs6terwJvE8cyRt1CzYYqzp9OrPhCT4cMc/f7C6RZCwG+qMmiffJS1/qJP8G1URtg==",
"dev": true,
"license": "MIT",
"dependencies": {
"@typescript-eslint/types": "8.63.0",
"@typescript-eslint/typescript-estree": "8.63.0",
"@typescript-eslint/utils": "8.63.0",
"@typescript-eslint/types": "8.64.0",
"@typescript-eslint/typescript-estree": "8.64.0",
"@typescript-eslint/utils": "8.64.0",
"debug": "^4.4.3",
"ts-api-utils": "^2.5.0"
},
@@ -3204,9 +3204,9 @@
}
},
"node_modules/@typescript-eslint/types": {
"version": "8.63.0",
"resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.63.0.tgz",
"integrity": "sha512-xyLtl9DUBBFrcJS4x2pIqGLH68/tC2uOa4Z7pUteW09D3bXnnXUom4dyPikzWgB7llmIc1zoeI3aoUdC4rPK/Q==",
"version": "8.64.0",
"resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.64.0.tgz",
"integrity": "sha512-qjhfuTfLXjA4IOzXvz0rTjT01BqEiIgPoUeMwiEjnaHKJMTNo8rH5pYW1a2L/0Dnux2fPC85AeyJoWaGa8WxTA==",
"dev": true,
"license": "MIT",
"engines": {
@@ -3218,16 +3218,16 @@
}
},
"node_modules/@typescript-eslint/typescript-estree": {
"version": "8.63.0",
"resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.63.0.tgz",
"integrity": "sha512-ygBkU+B7ex5UI/gKhaqexWev79uISfIv7XQCRNYO/jmD8rGLPyWLAb3KMRT6nd8Gt9bmUBi9+iX6tBdYfOY81Q==",
"version": "8.64.0",
"resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.64.0.tgz",
"integrity": "sha512-Pztpsn1aCE1oWDvDEfUk31nngvvF7vUB5SwHFEaZIFpvw7WJtqUHHL4plBZDA9HfWJJjL13BdG0YrJInTUvoVA==",
"dev": true,
"license": "MIT",
"dependencies": {
"@typescript-eslint/project-service": "8.63.0",
"@typescript-eslint/tsconfig-utils": "8.63.0",
"@typescript-eslint/types": "8.63.0",
"@typescript-eslint/visitor-keys": "8.63.0",
"@typescript-eslint/project-service": "8.64.0",
"@typescript-eslint/tsconfig-utils": "8.64.0",
"@typescript-eslint/types": "8.64.0",
"@typescript-eslint/visitor-keys": "8.64.0",
"debug": "^4.4.3",
"minimatch": "^10.2.2",
"semver": "^7.7.3",
@@ -3285,16 +3285,16 @@
}
},
"node_modules/@typescript-eslint/utils": {
"version": "8.63.0",
"resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.63.0.tgz",
"integrity": "sha512-fUKaeAvrTuQg/Tgt3nliAUSZHJM6DlCcfyEmxCvlX8kieWSStBX+5O5Fnidtc3i2JrH+9c/GL4RY2iasd/GPTA==",
"version": "8.64.0",
"resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.64.0.tgz",
"integrity": "sha512-aJUGVB3+U0htrrCjoA8qukw8cm8fNCGAxK/tVoS70k8aeb7DETKeFozRiVFIwEeN9WJLsjaP3ph8I60tY2XZoQ==",
"dev": true,
"license": "MIT",
"dependencies": {
"@eslint-community/eslint-utils": "^4.9.1",
"@typescript-eslint/scope-manager": "8.63.0",
"@typescript-eslint/types": "8.63.0",
"@typescript-eslint/typescript-estree": "8.63.0"
"@typescript-eslint/scope-manager": "8.64.0",
"@typescript-eslint/types": "8.64.0",
"@typescript-eslint/typescript-estree": "8.64.0"
},
"engines": {
"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
@@ -3309,13 +3309,13 @@
}
},
"node_modules/@typescript-eslint/visitor-keys": {
"version": "8.63.0",
"resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.63.0.tgz",
"integrity": "sha512-UexrHGnGTpbuQHct2ExOc2ZcFbGUS9FOesCxxqdBGcpI1BxYu/LZ6U8Aq6/72XtF/qRBk9nhuGHFJIXXMhPMdw==",
"version": "8.64.0",
"resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.64.0.tgz",
"integrity": "sha512-mrtuL8Nsn6gi2H4mo5KMTp823M+3Q19Ew/i+Zlikq20tIMm99C3Ez0dCmkWWnxut20esQvTg8aUSEhMcAOXhEw==",
"dev": true,
"license": "MIT",
"dependencies": {
"@typescript-eslint/types": "8.63.0",
"@typescript-eslint/types": "8.64.0",
"eslint-visitor-keys": "^5.0.0"
},
"engines": {
@@ -3920,9 +3920,9 @@
"license": "MIT"
},
"node_modules/autoprefixer": {
"version": "10.5.0",
"resolved": "https://registry.npmjs.org/autoprefixer/-/autoprefixer-10.5.0.tgz",
"integrity": "sha512-FMhOoZV4+qR6aTUALKX2rEqGG+oyATvwBt9IIzVR5rMa2HRWPkxf+P+PAJLD1I/H5/II+HuZcBJYEFBpq39ong==",
"version": "10.5.4",
"resolved": "https://registry.npmjs.org/autoprefixer/-/autoprefixer-10.5.4.tgz",
"integrity": "sha512-MaU0U/za7N3r6brxD4YB/l4NSrFzLPlANv6wEuQVaIPlD3L4W9rFcQPbL/EilY9BHhHvhfcz3gInDLrEtWT4EA==",
"dev": true,
"funding": [
{
@@ -3940,8 +3940,8 @@
],
"license": "MIT",
"dependencies": {
"browserslist": "^4.28.2",
"caniuse-lite": "^1.0.30001787",
"browserslist": "^4.28.6",
"caniuse-lite": "^1.0.30001806",
"fraction.js": "^5.3.4",
"picocolors": "^1.1.1",
"postcss-value-parser": "^4.2.0"
@@ -3976,9 +3976,9 @@
"license": "MIT"
},
"node_modules/baseline-browser-mapping": {
"version": "2.10.35",
"resolved": "https://registry.npmjs.org/baseline-browser-mapping/-/baseline-browser-mapping-2.10.35.tgz",
"integrity": "sha512-honAfLBde0HAFLdNyBEfuuENkF6zR+ozxqxa/2zJKHBe1qzLqyTSeRKpdPEHAP03rlDGyQOPnCSxnVpVqQo9Mg==",
"version": "2.10.44",
"resolved": "https://registry.npmjs.org/baseline-browser-mapping/-/baseline-browser-mapping-2.10.44.tgz",
"integrity": "sha512-T3ghW+sl/ZJ8w1v/yQx3qvJ9040DWoLBz8JT/CILbAKcFyG9b2MRe75v6W5uXjv6uH1lumK2Kv46y2zSkcej0Q==",
"dev": true,
"license": "Apache-2.0",
"bin": {
@@ -4030,9 +4030,9 @@
}
},
"node_modules/browserslist": {
"version": "4.28.2",
"resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.28.2.tgz",
"integrity": "sha512-48xSriZYYg+8qXna9kwqjIVzuQxi+KYWp2+5nCYnYKPTr0LvD89Jqk2Or5ogxz0NUMfIjhh2lIUX/LyX9B4oIg==",
"version": "4.28.6",
"resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.28.6.tgz",
"integrity": "sha512-FQBYNK15VMslhLHpA7+n+n1GOlF1kId2xcCg7/j95f24AOF6VDYMNH4mFxF7KuaTdv627faazpOAjFzMrfJOUw==",
"dev": true,
"funding": [
{
@@ -4051,10 +4051,10 @@
"license": "MIT",
"peer": true,
"dependencies": {
"baseline-browser-mapping": "^2.10.12",
"caniuse-lite": "^1.0.30001782",
"electron-to-chromium": "^1.5.328",
"node-releases": "^2.0.36",
"baseline-browser-mapping": "^2.10.42",
"caniuse-lite": "^1.0.30001803",
"electron-to-chromium": "^1.5.389",
"node-releases": "^2.0.51",
"update-browserslist-db": "^1.2.3"
},
"bin": {
@@ -4129,9 +4129,9 @@
}
},
"node_modules/caniuse-lite": {
"version": "1.0.30001797",
"resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001797.tgz",
"integrity": "sha512-l8xKG+gwAIExZGl9FrF7KUwuOmk6wbEPC9Xoy/RtnWv1XG0Q4LFlagaLpUv3Kiza3W/wm27zy0yWJEieYKAP6w==",
"version": "1.0.30001806",
"resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001806.tgz",
"integrity": "sha512-72Cuvd95zbSYPKq6Fhg8eDJRlzgWDf7/mtoZv6Qe/DYNCEBdNxoA3+rZAU2ZhGCpZlns3EssFavaZomckT5Uuw==",
"dev": true,
"funding": [
{
@@ -5154,9 +5154,9 @@
}
},
"node_modules/electron-to-chromium": {
"version": "1.5.376",
"resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.376.tgz",
"integrity": "sha512-cUVA7/RvbFTEuw/i3obUwDTRIXojaxkResf+ibByPFxjc6XK3VNtcQXV0NSbAlJ0FMjcJGgftVVB4Qo184EXvA==",
"version": "1.5.394",
"resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.394.tgz",
"integrity": "sha512-Wmt2Gm0o8JWBuGgmc4XZ0u9s1RaCRqhxP47phplmfg04+qypTUurpeJGP45A7Fhv7jdrrVH44PLlR9qXo37cVQ==",
"dev": true,
"license": "ISC"
},
@@ -7914,9 +7914,9 @@
"optional": true
},
"node_modules/node-releases": {
"version": "2.0.48",
"resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.48.tgz",
"integrity": "sha512-1uz8041X6LoI6ZSdZacM9lVY28vuzDlSKitnpbSNK0RfKoIJkX29NBPVEFXhnuSuEOA9Ww0xnPJ+ILWbGAv8DA==",
"version": "2.0.51",
"resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.51.tgz",
"integrity": "sha512-wRNIrw4DmVLKQlbgOMdkMx27Wrpzes2hh5Jtbi2bjPd+4wJstWIqP5A+lscnqbm0xxmT5Bpg8Lec5ItEBwx6BQ==",
"dev": true,
"license": "MIT",
"engines": {
@@ -8344,9 +8344,9 @@
}
},
"node_modules/prettier": {
"version": "3.8.2",
"resolved": "https://registry.npmjs.org/prettier/-/prettier-3.8.2.tgz",
"integrity": "sha512-8c3mgTe0ASwWAJK+78dpviD+A8EqhndQPUBpNUIPt6+xWlIigCwfN01lWr9MAede4uqXGTEKeQWTvzb3vjia0Q==",
"version": "3.9.5",
"resolved": "https://registry.npmjs.org/prettier/-/prettier-3.9.5.tgz",
"integrity": "sha512-/FVl766LpUfB5vXgCYOYa0MeV/441Ia99AeICQIQFTY/Nw0roZwULcXpku5i1/m5kt/baz+s4Zogspd839HSMg==",
"dev": true,
"license": "MIT",
"peer": true,
@@ -8813,9 +8813,9 @@
"license": "MIT"
},
"node_modules/sass": {
"version": "1.100.0",
"resolved": "https://registry.npmjs.org/sass/-/sass-1.100.0.tgz",
"integrity": "sha512-B5j0rYMlinhhOo9tjQebMVVn0TfyXAF+wB3b2ggZUuJ/is/Y+7+JGjirAMxHZ9Z3hIP98NPfamlAkBHa1lAaXQ==",
"version": "1.101.0",
"resolved": "https://registry.npmjs.org/sass/-/sass-1.101.0.tgz",
"integrity": "sha512-OL3GoQyoUdDt843DpVmDO6y2k1sc5IhUDSpu8XucEI+35neq5QivZ1iuegnpraEVTJXlQGK1gl27zKcTLEPbQw==",
"dev": true,
"license": "MIT",
"peer": true,
+5 -5
View File
@@ -63,12 +63,12 @@
"@tailwindcss/postcss": "^4.3.0",
"@types/node": "^26.1.1",
"@types/uuid": "^11.0.0",
"@typescript-eslint/eslint-plugin": "^8.63.0",
"@typescript-eslint/parser": "^8.63.0",
"@typescript-eslint/eslint-plugin": "^8.64.0",
"@typescript-eslint/parser": "^8.64.0",
"@vitejs/plugin-vue": "^6.0.7",
"@vitejs/plugin-vue-jsx": "^5.1.6",
"@vue/compiler-sfc": "^3.5.35",
"autoprefixer": "^10.5.0",
"autoprefixer": "^10.5.4",
"esbuild": "^0.28.1",
"eslint": "^10.6.0",
"eslint-config-prettier": "^10.1.8",
@@ -77,9 +77,9 @@
"lint-staged": "^17.0.7",
"postcss": "^8.5.14",
"postcss-html": "^1.8.1",
"prettier": "^3.8.2",
"prettier": "^3.9.5",
"rollup-plugin-visualizer": "^5.5.4",
"sass": "^1.100.0",
"sass": "^1.101.0",
"standard-version": "^9.5.0",
"tailwindcss": "^4.3.0",
"typescript": "^6.0.3",
+11
View File
@@ -0,0 +1,11 @@
import { reactive, type UnwrapNestedRefs } from 'vue';
import { useRoute } from 'vue-router';
import { useGlobalStore } from '@/composables/useGlobalStore';
import { getPageState } from '@/utils/page-state-cache';
export const usePageState = <T extends object>(factory: () => T): UnwrapNestedRefs<T> => {
const route = useRoute();
const { currentNode } = useGlobalStore();
const key = `${currentNode.value}:${String(route.name || route.path)}`;
return reactive(getPageState(key, factory));
};
+4
View File
@@ -4835,6 +4835,7 @@ const message = {
provinceRuleLabel: 'Province',
openRestyFeatureVersionAlert: 'OpenResty must be newer than 1.31.1.1-0 for {0} to take effect.',
ipLocation: 'IP Location',
ipLocationSearchHelper: 'Enter an IP location, fuzzy search supported',
action: 'Action',
ruleType: 'Attack Type',
ipHelper: 'Enter the IP address',
@@ -5042,6 +5043,9 @@ const message = {
observationModeConfirm:
'In observation mode, all WAF matches are logged without blocking requests. Continue?',
globalStrictRequired: 'Enable strict mode in global settings first',
websiteSearchHelper: 'Enter a website domain, alias, or remark',
configReadFailed: 'Failed to load configuration',
detailSetting: 'Detailed settings',
observe: 'Observe',
saveLog: 'Save Log',
remoteURLHelper: 'The remote URL needs to ensure one IP per line and no other characters',
+4
View File
@@ -4885,6 +4885,7 @@ const message = {
provinceRuleLabel: 'Provincia',
openRestyFeatureVersionAlert: 'OpenResty debe ser posterior a la versión 1.31.1.1-0 para que {0} funcione.',
ipLocation: 'Ubicación IP',
ipLocationSearchHelper: 'Introduzca la ubicación de la IP; se admite búsqueda aproximada',
action: 'Acción',
ruleType: 'Tipo de ataque',
ipHelper: 'Introduce la dirección IP',
@@ -5086,6 +5087,9 @@ const message = {
observationModeConfirm:
'En el modo de observación, todas las coincidencias del WAF se registran sin bloquear solicitudes. ¿Continuar?',
globalStrictRequired: 'Primero habilite el modo estricto en la configuración global',
websiteSearchHelper: 'Introduzca el dominio, alias o comentario del sitio web',
configReadFailed: 'No se pudo cargar la configuración',
detailSetting: 'Configuración detallada',
observe: 'Observar',
saveLog: 'Guardar log',
remoteURLHelper: 'La URL remota debe tener solo una IP por línea y sin otros caracteres',
+12
View File
@@ -4796,6 +4796,7 @@ const message = {
provincePolicy: 'سیاست استان',
openRestyFeatureVersionAlert: 'برای فعال شدن {0}، نسخه OpenResty باید جدیدتر از 1.31.1.1-0 باشد.',
ipLocation: 'مکان IP',
ipLocationSearchHelper: 'موقعیت IP را وارد کنید؛ جست‌وجوی تقریبی پشتیبانی می‌شود',
action: 'اقدام',
ruleType: 'نوع حمله',
ipHelper: 'آدرس IP را وارد کنید',
@@ -4991,6 +4992,17 @@ const message = {
crlf: 'تزریق CRLF',
strict: 'حالت سخت‌گیرانه',
strictHelper: 'از قوانین سخت‌گیرانه‌تر برای تأیید درخواست‌ها استفاده کنید',
executionStrategy: 'راهبرد اجرا',
detectionStrength: 'شدت تشخیص',
protectionMode: 'حالت محافظت',
observationMode: 'حالت مشاهده',
standardMode: 'حالت استاندارد',
observationModeConfirm:
'در حالت مشاهده، تمام موارد منطبق WAF فقط ثبت می‌شوند و درخواست‌ها مسدود نمی‌شوند. ادامه می‌دهید؟',
globalStrictRequired: 'ابتدا حالت سخت‌گیرانه را در تنظیمات سراسری فعال کنید',
websiteSearchHelper: 'دامنه، نام مستعار یا توضیحات وب‌سایت را وارد کنید',
configReadFailed: 'بارگذاری پیکربندی ناموفق بود',
detailSetting: 'تنظیمات دقیق',
saveLog: 'ذخیره لاگ',
remoteURLHelper: 'URL از راه دور باید تضمین کند که هر خط یک IP است و هیچ کاراکتر دیگری ندارد',
notFound: 'یافت نشد (۴۰۴)',
+4
View File
@@ -4849,6 +4849,7 @@ const message = {
openRestyFeatureVersionAlert:
'{0} を有効にするにはOpenResty のバージョンが 1.31.1.1-0 より新しい必要があります',
ipLocation: 'IP位置',
ipLocationSearchHelper: 'IP の所在地を入力してくださいあいまい検索対応',
action: 'アクション',
ruleType: '攻撃タイプ',
ipHelper: 'IPアドレスを入力してください',
@@ -5053,6 +5054,9 @@ const message = {
observationModeConfirm:
'監視モードではすべての WAF 検出をログに記録しリクエストをブロックしません続行しますか',
globalStrictRequired: '先にグローバル設定で厳格モードを有効にしてください',
websiteSearchHelper: 'サイトのドメインエイリアスまたは備考を入力してください',
configReadFailed: '設定の読み込みに失敗しました',
detailSetting: '詳細設定',
observe: '監視',
saveLog: 'ログを保存',
remoteURLHelper: 'リモート URL 1行に1つのIPで他の文字がないことを保証する必要があります',
+4
View File
@@ -4753,6 +4753,7 @@ const message = {
provinceRuleLabel: '성',
openRestyFeatureVersionAlert: '{0}() 적용하려면 OpenResty 버전이 1.31.1.1-0보다 높아야 합니다.',
ipLocation: 'IP 위치',
ipLocationSearchHelper: 'IP 위치를 입력하세요. 부분 검색을 지원합니다',
action: '동작',
ruleType: '공격 유형',
ipHelper: 'IP 주소를 입력하세요',
@@ -4953,6 +4954,9 @@ const message = {
observationModeConfirm:
'관찰 모드에서는 모든 WAF 탐지를 기록하지만 요청을 차단하지 않습니다. 계속하시겠습니까?',
globalStrictRequired: '먼저 전역 설정에서 엄격 모드를 활성화하세요',
websiteSearchHelper: '웹사이트 도메인, 별칭 또는 비고를 입력하세요',
configReadFailed: '설정을 불러오지 못했습니다',
detailSetting: '상세 설정',
observe: '관찰',
saveLog: '로그 저장',
remoteURLHelper: '원격 URL은 줄에 하나의 IP만 포함하고 다른 문자는 포함하지 않아야 합니다',
+4
View File
@@ -4912,6 +4912,7 @@ const message = {
provinceRuleLabel: 'Wilayah pentadbiran',
openRestyFeatureVersionAlert: 'OpenResty mesti lebih baharu daripada 1.31.1.1-0 agar {0} berfungsi.',
ipLocation: 'Lokasi IP',
ipLocationSearchHelper: 'Masukkan lokasi IP; carian kabur disokong',
action: 'Tindakan',
ruleType: 'Jenis Serangan',
ipHelper: 'Masukkan alamat IP',
@@ -5118,6 +5119,9 @@ const message = {
observationModeConfirm:
'Dalam mod pemerhatian, semua padanan WAF direkod tanpa menyekat permintaan. Teruskan?',
globalStrictRequired: 'Dayakan mod strict dalam tetapan global terlebih dahulu',
websiteSearchHelper: 'Masukkan domain, alias atau catatan laman web',
configReadFailed: 'Gagal memuatkan konfigurasi',
detailSetting: 'Tetapan terperinci',
observe: 'Perhati',
saveLog: 'Simpan Log',
remoteURLHelper: 'URL jauh perlu memastikan satu IP setiap baris dan tiada aksara lain',
+4
View File
@@ -5054,6 +5054,7 @@ const message = {
provinceRuleLabel: 'Província',
openRestyFeatureVersionAlert: 'A versão do OpenResty deve ser superior a 1.31.1.1-0 para que {0} funcione.',
ipLocation: 'Localização do IP',
ipLocationSearchHelper: 'Insira a localização do IP; pesquisa aproximada é suportada',
action: 'Ação',
ruleType: 'Tipo de ataque',
ipHelper: 'Digite o endereço IP',
@@ -5262,6 +5263,9 @@ const message = {
observationModeConfirm:
'No modo de observação, todas as correspondências do WAF são registradas sem bloquear solicitações. Continuar?',
globalStrictRequired: 'Primeiro habilite o modo estrito nas configurações globais',
websiteSearchHelper: 'Digite o domínio, alias ou observação do site',
configReadFailed: 'Falha ao carregar a configuração',
detailSetting: 'Configurações detalhadas',
observe: 'Observar',
saveLog: 'Salvar log',
remoteURLHelper: 'O URL remoto precisa garantir um IP por linha e nenhum outro caractere',
+4
View File
@@ -4900,6 +4900,7 @@ const message = {
provinceRuleLabel: 'Провинция',
openRestyFeatureVersionAlert: 'Для работы функции «{0}» требуется версия OpenResty новее 1.31.1.1-0.',
ipLocation: 'Местоположение IP',
ipLocationSearchHelper: 'Введите местоположение IP; поддерживается нечеткий поиск',
action: 'Действие',
ruleType: 'Тип атаки',
ipHelper: 'Введите IP-адрес',
@@ -5108,6 +5109,9 @@ const message = {
observationModeConfirm:
'В режиме наблюдения все срабатывания WAF записываются без блокировки запросов. Продолжить?',
globalStrictRequired: 'Сначала включите строгий режим в глобальных настройках',
websiteSearchHelper: 'Введите домен, псевдоним или примечание сайта',
configReadFailed: 'Не удалось загрузить конфигурацию',
detailSetting: 'Подробные настройки',
observe: 'Наблюдение',
saveLog: 'Сохранить лог',
remoteURLHelper: 'Удаленный URL должен содержать один IP на строку и не содержать других символов',
+4
View File
@@ -4897,6 +4897,7 @@ const message = {
openRestyFeatureVersionAlert:
'{0} özelliğinin çalışması için OpenResty sürümü 1.31.1.1-0 sürümünden daha yeni olmalıdır.',
ipLocation: 'IP Konumu',
ipLocationSearchHelper: 'IP konumunu girin; bulanık arama desteklenir',
action: 'Eylem',
ruleType: 'Saldırı Türü',
ipHelper: 'IP adresini girin',
@@ -5103,6 +5104,9 @@ const message = {
observationModeConfirm:
'Gözlem modunda tüm WAF eşleşmeleri istekler engellenmeden kaydedilir. Devam edilsin mi?',
globalStrictRequired: 'Önce genel ayarlarda katı modu etkinleştirin',
websiteSearchHelper: 'Web sitesi alan adı, takma adı veya açıklaması girin',
configReadFailed: 'Yapılandırma yüklenemedi',
detailSetting: 'Ayrıntılı ayarlar',
observe: 'Gözlem',
saveLog: 'Günlüğü Kaydet',
remoteURLHelper: 'Uzak URL, her satırda bir IP içermeli ve başka karakter olmamalıdır',
+4
View File
@@ -4498,6 +4498,7 @@ const message = {
provinceRuleLabel: '省份',
openRestyFeatureVersionAlert: 'OpenResty 版本需高於 1.31.1.1-0{0}才會生效',
ipLocation: 'IP 歸屬地',
ipLocationSearchHelper: '請輸入 IP 歸屬地支援模糊搜尋',
action: '動作',
ruleType: '攻擊類型',
ipHelper: '請輸入 IP',
@@ -4691,6 +4692,9 @@ const message = {
observationModeHelper: '僅檢測並記錄日誌不會攔截請求',
observationModeConfirm: '開啟觀察模式後所有 WAF 命中都只記錄日誌不會攔截請求是否繼續',
globalStrictRequired: '需要先在全域設定中開啟嚴格模式',
websiteSearchHelper: '請輸入網站網域別名或備註',
configReadFailed: '設定讀取失敗',
detailSetting: '詳細設定',
observe: '觀察',
saveLog: '儲存日誌',
remoteURLHelper: '遠端 URL 需要保證每行一個 IP 並且沒有其他字元',
+4
View File
@@ -3956,6 +3956,7 @@ const message = {
provinceRuleLabel: '省份',
openRestyFeatureVersionAlert: 'OpenResty 版本需高于 1.31.1.1-0{0}才会生效',
ipLocation: 'IP 归属地',
ipLocationSearchHelper: '请输入 IP 归属地支持模糊搜索',
action: '动作',
ruleType: '攻击类型',
ipHelper: '请输入 IP',
@@ -4149,6 +4150,9 @@ const message = {
observationModeHelper: '仅检测并记录日志不会拦截请求',
observationModeConfirm: '开启观察模式后所有 WAF 命中都只记录日志不会拦截请求是否继续',
globalStrictRequired: '需要先在全局设置中开启严格模式',
websiteSearchHelper: '请输入网站域名别名或备注',
configReadFailed: '配置读取失败',
detailSetting: '详细设置',
observe: '观察',
saveLog: '保存日志',
remoteURLHelper: '远程 URL 需要保证每行一个 IP 并且没有其他字符',
+2
View File
@@ -5,6 +5,7 @@ import { GlobalState } from '../interface';
import { DeviceType } from '@/enums/app';
import i18n, { setActiveLocale } from '@/lang';
import { isMasterOnlyPermissionCode, setMasterOnlyPermissionCodes, toManageCode } from '@/utils/permission-codes';
import { clearPageStateCache } from '@/utils/page-state-cache';
const CN_DOCS_URL = 'https://1panel.cn/docs/v2';
const INTL_DOCS_URL = 'https://docs.1panel.pro/v2';
@@ -121,6 +122,7 @@ const GlobalStore = defineStore('GlobalState', {
setMasterOnlyPermissionCodes(this.masterOnlyPermissions);
},
clearAuthInfo() {
clearPageStateCache();
this.permissions = [];
this.masterOnlyPermissions = [];
this.nodeRoles = [];
+15
View File
@@ -0,0 +1,15 @@
const pageStateCache = new Map<string, object>();
export const getPageState = <T extends object>(key: string, factory: () => T): T => {
const cached = pageStateCache.get(key) as T | undefined;
if (cached) {
return cached;
}
const state = factory();
pageStateCache.set(key, state);
return state;
};
export const clearPageStateCache = () => {
pageStateCache.clear();
};
+34 -15
View File
@@ -61,6 +61,11 @@
<template #main>
<ComplexTable
:pagination-config="paginationConfig"
:default-sort="
paginationConfig.order !== 'null'
? { prop: paginationConfig.orderBy, order: paginationConfig.order }
: undefined
"
v-model:view-mode="viewMode"
v-model:selects="selects"
@sort-change="search"
@@ -268,7 +273,7 @@
import Records from '@/views/cronjob/cronjob/record/index.vue';
import Backups from '@/views/cronjob/cronjob/backup/index.vue';
import Import from '@/views/cronjob/cronjob/import/index.vue';
import { onMounted, reactive, ref } from 'vue';
import { onMounted, ref, toRefs } from 'vue';
import {
deleteCronjob,
editCronjobGroup,
@@ -288,6 +293,7 @@ import { getGroupList } from '@/api/modules/group';
import { routerToNameWithQuery } from '@/utils/router';
import { useGlobalStore } from '@/composables/useGlobalStore';
import { useOperateNodeContext } from '@/composables/useOperateNodeContext';
import { usePageState } from '@/composables/usePageState';
const { currentNode, isMobile } = useGlobalStore();
useOperateNodeContext(currentNode);
@@ -306,24 +312,29 @@ const opExportRef = ref();
const dialogImportRef = ref();
const data = ref();
const paginationConfig = reactive({
cacheSizeKey: 'cronjob-page-size',
currentPage: 1,
pageSize: Number(localStorage.getItem('cronjob-page-size')) || 20,
total: 0,
orderBy: 'createdAt',
order: 'null',
});
const searchName = ref();
const defaultGroupID = ref<number>();
const searchGroupID = ref<number>();
const groupOptions = ref();
const dialogGroupRef = ref();
const pageState = usePageState(() => ({
paginationConfig: {
cacheSizeKey: 'cronjob-page-size',
currentPage: 1,
pageSize: Number(localStorage.getItem('cronjob-page-size')) || 20,
total: 0,
orderBy: 'createdAt',
order: 'null',
},
defaultGroupID: undefined as number | undefined,
searchName: undefined as string | undefined,
searchGroupID: undefined as number | undefined,
}));
const paginationConfig = pageState.paginationConfig;
const { defaultGroupID, searchName, searchGroupID } = toRefs(pageState);
const search = async (column?: any) => {
paginationConfig.orderBy = column?.order ? column.prop : paginationConfig.orderBy;
paginationConfig.order = column?.order ? column.order : paginationConfig.order;
if (column) {
paginationConfig.orderBy = column.order ? column.prop : 'createdAt';
paginationConfig.order = column.order || 'null';
}
let groupIDs;
if (searchGroupID.value) {
groupIDs = searchGroupID.value === defaultGroupID.value ? [searchGroupID.value, 0] : [searchGroupID.value];
@@ -454,6 +465,11 @@ const onSubmitExport = async () => {
const loadGroups = async () => {
const res = await getGroupList('cronjob');
groupOptions.value = res.data || [];
const invalidGroup = searchGroupID.value && !groupOptions.value.some((group) => group.id === searchGroupID.value);
if (invalidGroup) {
searchGroupID.value = undefined;
paginationConfig.currentPage = 1;
}
for (const group of groupOptions.value) {
if (group.name === 'Default') {
defaultGroupID.value = group.id;
@@ -478,6 +494,9 @@ const loadGroups = async () => {
item.groupBelong = '-';
}
}
if (invalidGroup) {
search();
}
};
const updateGroup = async (row: any) => {
+42 -18
View File
@@ -67,6 +67,7 @@
<template v-if="!openNginxConfig" #main>
<ComplexTable
:pagination-config="paginationConfig"
:default-sort="tableSort.order ? tableSort : undefined"
v-model:view-mode="viewMode"
:data="data"
@sort-change="changeSort"
@@ -371,6 +372,7 @@ import { getWebsiteTypes } from '@/global/mimetype';
import { routerToFileWithPath, routerToNameWithParams, routerToNameWithQuery } from '@/utils/router';
import { useGlobalStore } from '@/composables/useGlobalStore';
import { useOperateNodeContext } from '@/composables/useOperateNodeContext';
import { usePageState } from '@/composables/usePageState';
const { currentNode, isMobile } = useGlobalStore();
useOperateNodeContext(currentNode);
@@ -423,21 +425,30 @@ const batchSetHttpsRef = ref();
const nginxVersion = ref();
const appStatusRef = ref();
const paginationConfig = reactive({
cacheSizeKey: 'website-page-size',
currentPage: 1,
pageSize: Number(localStorage.getItem('website-page-size')) || 20,
total: 0,
});
let req = reactive({
name: '',
page: 1,
pageSize: 10,
orderBy: 'favorite',
order: 'descending',
websiteGroupId: 0,
type: '',
});
const pageState = usePageState(() => ({
paginationConfig: {
cacheSizeKey: 'website-page-size',
currentPage: 1,
pageSize: Number(localStorage.getItem('website-page-size')) || 20,
total: 0,
},
req: {
name: '',
page: 1,
pageSize: 10,
orderBy: 'favorite',
order: 'descending',
websiteGroupId: 0,
type: '',
},
tableSort: {
prop: '',
order: null as 'ascending' | 'descending' | null,
},
}));
const paginationConfig = pageState.paginationConfig;
const req = pageState.req;
const tableSort = pageState.tableSort;
const goRouter = async (key: string) => {
routerToNameWithQuery('AppAll', { install: key });
@@ -466,6 +477,8 @@ const disabledConfig = computed(() => {
});
const changeSort = ({ prop, order }) => {
tableSort.prop = prop || '';
tableSort.order = order || null;
if (order) {
switch (prop) {
case 'primaryDomain':
@@ -502,9 +515,16 @@ const search = async () => {
});
};
const listGroup = async () => {
const listGroup = async (searchOnReset = true) => {
const res = await getAgentGroupList('website');
groups.value = res.data;
if (req.websiteGroupId !== 0 && !groups.value.some((group) => group.id === req.websiteGroupId)) {
req.websiteGroupId = 0;
paginationConfig.currentPage = 1;
if (searchOnReset) {
search();
}
}
};
const setting = () => {
@@ -728,9 +748,13 @@ const batchOp = () => {
}
};
onMounted(() => {
onMounted(async () => {
try {
await listGroup(false);
} catch {
// The request interceptor already reports the error; website loading should continue.
}
search();
listGroup();
});
</script>
+33
View File
@@ -0,0 +1,33 @@
import assert from 'node:assert/strict';
import test from 'node:test';
import { clearPageStateCache, getPageState } from '../src/utils/page-state-cache.ts';
test('reuses state for the same page key', () => {
clearPageStateCache();
const first = getPageState('local:Website', () => ({ name: '' }));
first.name = 'example.com';
const second = getPageState('local:Website', () => ({ name: 'ignored' }));
assert.equal(second.name, 'example.com');
assert.equal(second, first);
});
test('isolates state by page key', () => {
clearPageStateCache();
const local = getPageState('local:Website', () => ({ name: 'local' }));
const remote = getPageState('remote:Website', () => ({ name: 'remote' }));
assert.notEqual(remote, local);
assert.equal(remote.name, 'remote');
});
test('creates fresh state after clearing the cache', () => {
const first = getPageState('local:Website', () => ({ page: 2 }));
clearPageStateCache();
const second = getPageState('local:Website', () => ({ page: 1 }));
assert.notEqual(second, first);
assert.equal(second.page, 1);
});