mirror of
https://github.com/TeaOSLab/EdgeAdmin.git
synced 2025-11-09 16:50:26 +08:00
增加刷新、预热缓存任务管理
This commit is contained in:
@@ -219,6 +219,14 @@ func (this *RPCClient) HTTPCachePolicyRPC() pb.HTTPCachePolicyServiceClient {
|
|||||||
return pb.NewHTTPCachePolicyServiceClient(this.pickConn())
|
return pb.NewHTTPCachePolicyServiceClient(this.pickConn())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (this *RPCClient) HTTPCacheTaskRPC() pb.HTTPCacheTaskServiceClient {
|
||||||
|
return pb.NewHTTPCacheTaskServiceClient(this.pickConn())
|
||||||
|
}
|
||||||
|
|
||||||
|
func (this *RPCClient) HTTPCacheTaskKeyRPC() pb.HTTPCacheTaskKeyServiceClient {
|
||||||
|
return pb.NewHTTPCacheTaskKeyServiceClient(this.pickConn())
|
||||||
|
}
|
||||||
|
|
||||||
func (this *RPCClient) HTTPFirewallPolicyRPC() pb.HTTPFirewallPolicyServiceClient {
|
func (this *RPCClient) HTTPFirewallPolicyRPC() pb.HTTPFirewallPolicyServiceClient {
|
||||||
return pb.NewHTTPFirewallPolicyServiceClient(this.pickConn())
|
return pb.NewHTTPFirewallPolicyServiceClient(this.pickConn())
|
||||||
}
|
}
|
||||||
|
|||||||
28
internal/web/actions/default/servers/components/cache/batch/deleteTask.go
vendored
Normal file
28
internal/web/actions/default/servers/components/cache/batch/deleteTask.go
vendored
Normal file
@@ -0,0 +1,28 @@
|
|||||||
|
// Copyright 2022 Liuxiangchao iwind.liu@gmail.com. All rights reserved. Official site: https://goedge.cn .
|
||||||
|
|
||||||
|
package cache
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
|
||||||
|
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
|
||||||
|
)
|
||||||
|
|
||||||
|
type DeleteTaskAction struct {
|
||||||
|
actionutils.ParentAction
|
||||||
|
}
|
||||||
|
|
||||||
|
func (this *DeleteTaskAction) RunPost(params struct {
|
||||||
|
TaskId int64
|
||||||
|
}) {
|
||||||
|
defer this.CreateLogInfo("删除缓存任务 %d", params.TaskId)
|
||||||
|
|
||||||
|
_, err := this.RPC().HTTPCacheTaskRPC().DeleteHTTPCacheTask(this.AdminContext(), &pb.DeleteHTTPCacheTaskRequest{
|
||||||
|
HttpCacheTaskId: params.TaskId,
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
this.ErrorPage(err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
this.Success()
|
||||||
|
}
|
||||||
96
internal/web/actions/default/servers/components/cache/batch/fetch.go
vendored
Normal file
96
internal/web/actions/default/servers/components/cache/batch/fetch.go
vendored
Normal file
@@ -0,0 +1,96 @@
|
|||||||
|
// Copyright 2022 Liuxiangchao iwind.liu@gmail.com. All rights reserved. Official site: https://goedge.cn .
|
||||||
|
|
||||||
|
package cache
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
|
||||||
|
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/default/servers/components/cache/cacheutils"
|
||||||
|
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
|
||||||
|
"github.com/iwind/TeaGo/actions"
|
||||||
|
"github.com/iwind/TeaGo/lists"
|
||||||
|
"github.com/iwind/TeaGo/maps"
|
||||||
|
"github.com/iwind/TeaGo/types"
|
||||||
|
"strings"
|
||||||
|
)
|
||||||
|
|
||||||
|
type FetchAction struct {
|
||||||
|
actionutils.ParentAction
|
||||||
|
}
|
||||||
|
|
||||||
|
func (this *FetchAction) Init() {
|
||||||
|
this.Nav("", "", "fetch")
|
||||||
|
}
|
||||||
|
|
||||||
|
func (this *FetchAction) RunGet(params struct{}) {
|
||||||
|
// 初始化菜单数据
|
||||||
|
err := InitMenu(this.Parent())
|
||||||
|
if err != nil {
|
||||||
|
this.ErrorPage(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
this.Show()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (this *FetchAction) RunPost(params struct {
|
||||||
|
Keys string
|
||||||
|
|
||||||
|
Must *actions.Must
|
||||||
|
CSRF *actionutils.CSRF
|
||||||
|
}) {
|
||||||
|
defer this.CreateLogInfo("批量预热缓存Key")
|
||||||
|
|
||||||
|
if len(params.Keys) == 0 {
|
||||||
|
this.Fail("请输入要预热的Key列表")
|
||||||
|
}
|
||||||
|
|
||||||
|
// 检查Key
|
||||||
|
var realKeys = []string{}
|
||||||
|
for _, key := range strings.Split(params.Keys, "\n") {
|
||||||
|
key = strings.TrimSpace(key)
|
||||||
|
if len(key) == 0 {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if lists.ContainsString(realKeys, key) {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
realKeys = append(realKeys, key)
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(realKeys) == 0 {
|
||||||
|
this.Fail("请输入要预热的Key列表")
|
||||||
|
}
|
||||||
|
|
||||||
|
// 校验Key
|
||||||
|
validateResp, err := this.RPC().HTTPCacheTaskKeyRPC().ValidateHTTPCacheTaskKeys(this.AdminContext(), &pb.ValidateHTTPCacheTaskKeysRequest{Keys: realKeys})
|
||||||
|
if err != nil {
|
||||||
|
this.ErrorPage(err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
var failKeyMaps = []maps.Map{}
|
||||||
|
if len(validateResp.FailKeys) > 0 {
|
||||||
|
for _, key := range validateResp.FailKeys {
|
||||||
|
failKeyMaps = append(failKeyMaps, maps.Map{
|
||||||
|
"key": key.Key,
|
||||||
|
"reason": cacheutils.KeyFailReason(key.ReasonCode),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
this.Data["failKeys"] = failKeyMaps
|
||||||
|
if len(failKeyMaps) > 0 {
|
||||||
|
this.Fail("有" + types.String(len(failKeyMaps)) + "个Key无法完成操作,请删除后重试")
|
||||||
|
}
|
||||||
|
|
||||||
|
// 提交任务
|
||||||
|
_, err = this.RPC().HTTPCacheTaskRPC().CreateHTTPCacheTask(this.AdminContext(), &pb.CreateHTTPCacheTaskRequest{
|
||||||
|
Type: "fetch",
|
||||||
|
KeyType: "key",
|
||||||
|
Keys: realKeys,
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
this.ErrorPage(err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
this.Success()
|
||||||
|
}
|
||||||
97
internal/web/actions/default/servers/components/cache/batch/index.go
vendored
Normal file
97
internal/web/actions/default/servers/components/cache/batch/index.go
vendored
Normal file
@@ -0,0 +1,97 @@
|
|||||||
|
// Copyright 2022 Liuxiangchao iwind.liu@gmail.com. All rights reserved. Official site: https://goedge.cn .
|
||||||
|
|
||||||
|
package cache
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
|
||||||
|
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/default/servers/components/cache/cacheutils"
|
||||||
|
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
|
||||||
|
"github.com/iwind/TeaGo/actions"
|
||||||
|
"github.com/iwind/TeaGo/lists"
|
||||||
|
"github.com/iwind/TeaGo/maps"
|
||||||
|
"github.com/iwind/TeaGo/types"
|
||||||
|
"strings"
|
||||||
|
)
|
||||||
|
|
||||||
|
type IndexAction struct {
|
||||||
|
actionutils.ParentAction
|
||||||
|
}
|
||||||
|
|
||||||
|
func (this *IndexAction) Init() {
|
||||||
|
this.Nav("", "", "purge")
|
||||||
|
}
|
||||||
|
|
||||||
|
func (this *IndexAction) RunGet(params struct{}) {
|
||||||
|
// 初始化菜单数据
|
||||||
|
err := InitMenu(this.Parent())
|
||||||
|
if err != nil {
|
||||||
|
this.ErrorPage(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
this.Show()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (this *IndexAction) RunPost(params struct {
|
||||||
|
KeyType string
|
||||||
|
Keys string
|
||||||
|
|
||||||
|
Must *actions.Must
|
||||||
|
CSRF *actionutils.CSRF
|
||||||
|
}) {
|
||||||
|
defer this.CreateLogInfo("批量刷新缓存Key")
|
||||||
|
|
||||||
|
if len(params.Keys) == 0 {
|
||||||
|
this.Fail("请输入要刷新的Key列表")
|
||||||
|
}
|
||||||
|
|
||||||
|
// 检查Key
|
||||||
|
var realKeys = []string{}
|
||||||
|
for _, key := range strings.Split(params.Keys, "\n") {
|
||||||
|
key = strings.TrimSpace(key)
|
||||||
|
if len(key) == 0 {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if lists.ContainsString(realKeys, key) {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
realKeys = append(realKeys, key)
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(realKeys) == 0 {
|
||||||
|
this.Fail("请输入要刷新的Key列表")
|
||||||
|
}
|
||||||
|
|
||||||
|
// 校验Key
|
||||||
|
validateResp, err := this.RPC().HTTPCacheTaskKeyRPC().ValidateHTTPCacheTaskKeys(this.AdminContext(), &pb.ValidateHTTPCacheTaskKeysRequest{Keys: realKeys})
|
||||||
|
if err != nil {
|
||||||
|
this.ErrorPage(err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
var failKeyMaps = []maps.Map{}
|
||||||
|
if len(validateResp.FailKeys) > 0 {
|
||||||
|
for _, key := range validateResp.FailKeys {
|
||||||
|
failKeyMaps = append(failKeyMaps, maps.Map{
|
||||||
|
"key": key.Key,
|
||||||
|
"reason": cacheutils.KeyFailReason(key.ReasonCode),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
this.Data["failKeys"] = failKeyMaps
|
||||||
|
if len(failKeyMaps) > 0 {
|
||||||
|
this.Fail("有" + types.String(len(failKeyMaps)) + "个Key无法完成操作,请删除后重试")
|
||||||
|
}
|
||||||
|
|
||||||
|
// 提交任务
|
||||||
|
_, err = this.RPC().HTTPCacheTaskRPC().CreateHTTPCacheTask(this.AdminContext(), &pb.CreateHTTPCacheTaskRequest{
|
||||||
|
Type: "purge",
|
||||||
|
KeyType: params.KeyType,
|
||||||
|
Keys: realKeys,
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
this.ErrorPage(err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
this.Success()
|
||||||
|
}
|
||||||
24
internal/web/actions/default/servers/components/cache/batch/init.go
vendored
Normal file
24
internal/web/actions/default/servers/components/cache/batch/init.go
vendored
Normal file
@@ -0,0 +1,24 @@
|
|||||||
|
package cache
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/TeaOSLab/EdgeAdmin/internal/configloaders"
|
||||||
|
"github.com/TeaOSLab/EdgeAdmin/internal/web/helpers"
|
||||||
|
"github.com/iwind/TeaGo"
|
||||||
|
)
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
TeaGo.BeforeStart(func(server *TeaGo.Server) {
|
||||||
|
server.
|
||||||
|
Helper(helpers.NewUserMustAuth(configloaders.AdminModuleCodeServer)).
|
||||||
|
Data("teaMenu", "servers").
|
||||||
|
Data("teaSubMenu", "cacheBatch").
|
||||||
|
Prefix("/servers/components/cache/batch").
|
||||||
|
GetPost("", new(IndexAction)).
|
||||||
|
GetPost("/fetch", new(FetchAction)).
|
||||||
|
Get("/tasks", new(TasksAction)).
|
||||||
|
Get("/task", new(TaskAction)).
|
||||||
|
Post("/deleteTask", new(DeleteTaskAction)).
|
||||||
|
Post("/resetTask", new(ResetTaskAction)).
|
||||||
|
EndAll()
|
||||||
|
})
|
||||||
|
}
|
||||||
26
internal/web/actions/default/servers/components/cache/batch/resetTask.go
vendored
Normal file
26
internal/web/actions/default/servers/components/cache/batch/resetTask.go
vendored
Normal file
@@ -0,0 +1,26 @@
|
|||||||
|
// Copyright 2022 Liuxiangchao iwind.liu@gmail.com. All rights reserved. Official site: https://goedge.cn .
|
||||||
|
|
||||||
|
package cache
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
|
||||||
|
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
|
||||||
|
)
|
||||||
|
|
||||||
|
type ResetTaskAction struct {
|
||||||
|
actionutils.ParentAction
|
||||||
|
}
|
||||||
|
|
||||||
|
func (this *ResetTaskAction) RunPost(params struct {
|
||||||
|
TaskId int64
|
||||||
|
}) {
|
||||||
|
this.CreateLogInfo("重置缓存任务 %d 状态", params.TaskId)
|
||||||
|
|
||||||
|
_, err := this.RPC().HTTPCacheTaskRPC().ResetHTTPCacheTask(this.AdminContext(), &pb.ResetHTTPCacheTaskRequest{HttpCacheTaskId: params.TaskId})
|
||||||
|
if err != nil {
|
||||||
|
this.ErrorPage(err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
this.Success()
|
||||||
|
}
|
||||||
104
internal/web/actions/default/servers/components/cache/batch/task.go
vendored
Normal file
104
internal/web/actions/default/servers/components/cache/batch/task.go
vendored
Normal file
@@ -0,0 +1,104 @@
|
|||||||
|
// Copyright 2022 Liuxiangchao iwind.liu@gmail.com. All rights reserved. Official site: https://goedge.cn .
|
||||||
|
|
||||||
|
package cache
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/json"
|
||||||
|
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
|
||||||
|
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
|
||||||
|
"github.com/iwind/TeaGo/maps"
|
||||||
|
timeutil "github.com/iwind/TeaGo/utils/time"
|
||||||
|
"sort"
|
||||||
|
)
|
||||||
|
|
||||||
|
type TaskAction struct {
|
||||||
|
actionutils.ParentAction
|
||||||
|
}
|
||||||
|
|
||||||
|
func (this *TaskAction) Init() {
|
||||||
|
this.Nav("", "", "task")
|
||||||
|
}
|
||||||
|
|
||||||
|
func (this *TaskAction) RunGet(params struct {
|
||||||
|
TaskId int64
|
||||||
|
}) {
|
||||||
|
// 初始化菜单数据
|
||||||
|
err := InitMenu(this.Parent())
|
||||||
|
if err != nil {
|
||||||
|
this.ErrorPage(err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
taskResp, err := this.RPC().HTTPCacheTaskRPC().FindEnabledHTTPCacheTask(this.AdminContext(), &pb.FindEnabledHTTPCacheTaskRequest{HttpCacheTaskId: params.TaskId})
|
||||||
|
if err != nil {
|
||||||
|
this.ErrorPage(err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
var task = taskResp.HttpCacheTask
|
||||||
|
if task == nil {
|
||||||
|
this.NotFound("HTTPCacheTask", params.TaskId)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// 用户
|
||||||
|
var userMap = maps.Map{"id": 0, "username": "", "fullname": ""}
|
||||||
|
if task.User != nil {
|
||||||
|
userMap = maps.Map{
|
||||||
|
"id": task.User.Id,
|
||||||
|
"username": task.User.Username,
|
||||||
|
"fullname": task.User.Fullname,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// keys
|
||||||
|
var keyMaps = []maps.Map{}
|
||||||
|
for _, key := range task.HttpCacheTaskKeys {
|
||||||
|
// 错误信息
|
||||||
|
var errorMaps = []maps.Map{}
|
||||||
|
|
||||||
|
if len(key.ErrorsJSON) > 0 {
|
||||||
|
var m = map[int64]string{}
|
||||||
|
err = json.Unmarshal(key.ErrorsJSON, &m)
|
||||||
|
if err != nil {
|
||||||
|
this.ErrorPage(err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
for nodeId, errString := range m {
|
||||||
|
errorMaps = append(errorMaps, maps.Map{
|
||||||
|
"nodeId": nodeId,
|
||||||
|
"error": errString,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 错误信息排序
|
||||||
|
if len(errorMaps) > 0 {
|
||||||
|
sort.Slice(errorMaps, func(i, j int) bool {
|
||||||
|
var m1 = errorMaps[i]
|
||||||
|
var m2 = errorMaps[j]
|
||||||
|
|
||||||
|
return m1.GetInt64("nodeId") < m2.GetInt64("nodeId")
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
keyMaps = append(keyMaps, maps.Map{
|
||||||
|
"key": key.Key,
|
||||||
|
"isDone": key.IsDone,
|
||||||
|
"errors": errorMaps,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
this.Data["task"] = maps.Map{
|
||||||
|
"id": task.Id,
|
||||||
|
"type": task.Type,
|
||||||
|
"keyType": task.KeyType,
|
||||||
|
"createdTime": timeutil.FormatTime("Y-m-d H:i:s", task.CreatedAt),
|
||||||
|
"doneTime": timeutil.FormatTime("Y-m-d H:i:s", task.DoneAt),
|
||||||
|
"isDone": task.IsDone,
|
||||||
|
"isOk": task.IsOk,
|
||||||
|
"keys": keyMaps,
|
||||||
|
"user": userMap,
|
||||||
|
}
|
||||||
|
|
||||||
|
this.Show()
|
||||||
|
}
|
||||||
72
internal/web/actions/default/servers/components/cache/batch/tasks.go
vendored
Normal file
72
internal/web/actions/default/servers/components/cache/batch/tasks.go
vendored
Normal file
@@ -0,0 +1,72 @@
|
|||||||
|
// Copyright 2022 Liuxiangchao iwind.liu@gmail.com. All rights reserved. Official site: https://goedge.cn .
|
||||||
|
|
||||||
|
package cache
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
|
||||||
|
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
|
||||||
|
"github.com/iwind/TeaGo/maps"
|
||||||
|
timeutil "github.com/iwind/TeaGo/utils/time"
|
||||||
|
)
|
||||||
|
|
||||||
|
type TasksAction struct {
|
||||||
|
actionutils.ParentAction
|
||||||
|
}
|
||||||
|
|
||||||
|
func (this *TasksAction) Init() {
|
||||||
|
this.Nav("", "", "task")
|
||||||
|
}
|
||||||
|
|
||||||
|
func (this *TasksAction) RunGet(params struct{}) {
|
||||||
|
// 初始化菜单数据
|
||||||
|
err := InitMenu(this.Parent())
|
||||||
|
if err != nil {
|
||||||
|
this.ErrorPage(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// 任务数量
|
||||||
|
countResp, err := this.RPC().HTTPCacheTaskRPC().CountHTTPCacheTasks(this.AdminContext(), &pb.CountHTTPCacheTasksRequest{})
|
||||||
|
if err != nil {
|
||||||
|
this.ErrorPage(err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
var count = countResp.Count
|
||||||
|
var page = this.NewPage(count)
|
||||||
|
this.Data["page"] = page.AsHTML()
|
||||||
|
|
||||||
|
// 任务列表
|
||||||
|
var taskMaps = []maps.Map{}
|
||||||
|
tasksResp, err := this.RPC().HTTPCacheTaskRPC().ListHTTPCacheTasks(this.AdminContext(), &pb.ListHTTPCacheTasksRequest{
|
||||||
|
Offset: page.Offset,
|
||||||
|
Size: page.Size,
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
this.ErrorPage(err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
for _, task := range tasksResp.HttpCacheTasks {
|
||||||
|
var userMap = maps.Map{"id": 0, "username": "", "fullname": ""}
|
||||||
|
if task.User != nil {
|
||||||
|
userMap = maps.Map{
|
||||||
|
"id": task.User.Id,
|
||||||
|
"username": task.User.Username,
|
||||||
|
"fullname": task.User.Fullname,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
taskMaps = append(taskMaps, maps.Map{
|
||||||
|
"id": task.Id,
|
||||||
|
"type": task.Type,
|
||||||
|
"keyType": task.KeyType,
|
||||||
|
"isDone": task.IsDone,
|
||||||
|
"isOk": task.IsOk,
|
||||||
|
"createdTime": timeutil.FormatTime("Y-m-d H:i:s", task.CreatedAt),
|
||||||
|
"description": task.Description,
|
||||||
|
"user": userMap,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
this.Data["tasks"] = taskMaps
|
||||||
|
|
||||||
|
this.Show()
|
||||||
|
}
|
||||||
24
internal/web/actions/default/servers/components/cache/batch/utils.go
vendored
Normal file
24
internal/web/actions/default/servers/components/cache/batch/utils.go
vendored
Normal file
@@ -0,0 +1,24 @@
|
|||||||
|
// Copyright 2022 Liuxiangchao iwind.liu@gmail.com. All rights reserved. Official site: https://goedge.cn .
|
||||||
|
|
||||||
|
package cache
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/TeaOSLab/EdgeAdmin/internal/rpc"
|
||||||
|
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
|
||||||
|
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
|
||||||
|
)
|
||||||
|
|
||||||
|
func InitMenu(parent *actionutils.ParentAction) error {
|
||||||
|
rpcClient, err := rpc.SharedRPC()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
countTasksResp, err := rpcClient.HTTPCacheTaskRPC().CountDoingHTTPCacheTasks(parent.AdminContext(), &pb.CountDoingHTTPCacheTasksRequest{})
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
parent.Data["countDoingTasks"] = countTasksResp.Count
|
||||||
|
return nil
|
||||||
|
}
|
||||||
@@ -8,7 +8,7 @@ import (
|
|||||||
"github.com/TeaOSLab/EdgeCommon/pkg/serverconfigs"
|
"github.com/TeaOSLab/EdgeCommon/pkg/serverconfigs"
|
||||||
)
|
)
|
||||||
|
|
||||||
// 查找缓存策略名称并忽略错误
|
// FindCachePolicyNameWithoutError 查找缓存策略名称并忽略错误
|
||||||
func FindCachePolicyNameWithoutError(parent *actionutils.ParentAction, cachePolicyId int64) string {
|
func FindCachePolicyNameWithoutError(parent *actionutils.ParentAction, cachePolicyId int64) string {
|
||||||
policy, err := FindCachePolicy(parent, cachePolicyId)
|
policy, err := FindCachePolicy(parent, cachePolicyId)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -20,7 +20,7 @@ func FindCachePolicyNameWithoutError(parent *actionutils.ParentAction, cachePoli
|
|||||||
return policy.Name
|
return policy.Name
|
||||||
}
|
}
|
||||||
|
|
||||||
// 查找缓存策略配置
|
// FindCachePolicy 查找缓存策略配置
|
||||||
func FindCachePolicy(parent *actionutils.ParentAction, cachePolicyId int64) (*serverconfigs.HTTPCachePolicy, error) {
|
func FindCachePolicy(parent *actionutils.ParentAction, cachePolicyId int64) (*serverconfigs.HTTPCachePolicy, error) {
|
||||||
resp, err := parent.RPC().HTTPCachePolicyRPC().FindEnabledHTTPCachePolicyConfig(parent.AdminContext(), &pb.FindEnabledHTTPCachePolicyConfigRequest{HttpCachePolicyId: cachePolicyId})
|
resp, err := parent.RPC().HTTPCachePolicyRPC().FindEnabledHTTPCachePolicyConfig(parent.AdminContext(), &pb.FindEnabledHTTPCachePolicyConfigRequest{HttpCachePolicyId: cachePolicyId})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -36,3 +36,20 @@ func FindCachePolicy(parent *actionutils.ParentAction, cachePolicyId int64) (*se
|
|||||||
}
|
}
|
||||||
return config, nil
|
return config, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// KeyFailReason Key相关失败原因
|
||||||
|
func KeyFailReason(reasonCode string) string {
|
||||||
|
switch reasonCode {
|
||||||
|
case "requireKey":
|
||||||
|
return "空的Key"
|
||||||
|
case "requireDomain":
|
||||||
|
return "找不到Key对应的域名"
|
||||||
|
case "requireServer":
|
||||||
|
return "找不到Key对应的网站服务"
|
||||||
|
case "requireUser":
|
||||||
|
return "该域名不属于当前用户"
|
||||||
|
case "requireClusterId":
|
||||||
|
return "该网站没有部署到集群"
|
||||||
|
}
|
||||||
|
return "未知错误"
|
||||||
|
}
|
||||||
|
|||||||
@@ -3,8 +3,7 @@ package cache
|
|||||||
import (
|
import (
|
||||||
"github.com/TeaOSLab/EdgeAdmin/internal/oplogs"
|
"github.com/TeaOSLab/EdgeAdmin/internal/oplogs"
|
||||||
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
|
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
|
||||||
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/default/nodes/nodeutils"
|
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/default/servers/components/cache/cacheutils"
|
||||||
"github.com/TeaOSLab/EdgeCommon/pkg/messageconfigs"
|
|
||||||
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
|
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
|
||||||
"github.com/iwind/TeaGo/actions"
|
"github.com/iwind/TeaGo/actions"
|
||||||
"github.com/iwind/TeaGo/lists"
|
"github.com/iwind/TeaGo/lists"
|
||||||
@@ -15,15 +14,15 @@ import (
|
|||||||
"strings"
|
"strings"
|
||||||
)
|
)
|
||||||
|
|
||||||
type PreheatAction struct {
|
type FetchAction struct {
|
||||||
actionutils.ParentAction
|
actionutils.ParentAction
|
||||||
}
|
}
|
||||||
|
|
||||||
func (this *PreheatAction) Init() {
|
func (this *FetchAction) Init() {
|
||||||
this.Nav("", "", "preheat")
|
this.Nav("", "", "fetch")
|
||||||
}
|
}
|
||||||
|
|
||||||
func (this *PreheatAction) RunGet(params struct {
|
func (this *FetchAction) RunGet(params struct {
|
||||||
CachePolicyId int64
|
CachePolicyId int64
|
||||||
}) {
|
}) {
|
||||||
// 默认的集群ID
|
// 默认的集群ID
|
||||||
@@ -50,7 +49,7 @@ func (this *PreheatAction) RunGet(params struct {
|
|||||||
this.Show()
|
this.Show()
|
||||||
}
|
}
|
||||||
|
|
||||||
func (this *PreheatAction) RunPost(params struct {
|
func (this *FetchAction) RunPost(params struct {
|
||||||
CachePolicyId int64
|
CachePolicyId int64
|
||||||
ClusterId int64
|
ClusterId int64
|
||||||
Keys string
|
Keys string
|
||||||
@@ -92,27 +91,38 @@ func (this *PreheatAction) RunPost(params struct {
|
|||||||
realKeys = append(realKeys, key)
|
realKeys = append(realKeys, key)
|
||||||
}
|
}
|
||||||
|
|
||||||
// 发送命令
|
// 校验Key
|
||||||
msg := &messageconfigs.PreheatCacheMessage{
|
// 这里暂时不校验服务ID
|
||||||
CachePolicyJSON: cachePolicyJSON,
|
validateResp, err := this.RPC().HTTPCacheTaskKeyRPC().ValidateHTTPCacheTaskKeys(this.AdminContext(), &pb.ValidateHTTPCacheTaskKeysRequest{Keys: realKeys})
|
||||||
Keys: realKeys,
|
|
||||||
}
|
|
||||||
results, err := nodeutils.SendMessageToCluster(this.AdminContext(), params.ClusterId, messageconfigs.MessageCodePreheatCache, msg, 300)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
this.ErrorPage(err)
|
this.ErrorPage(err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
isAllOk := true
|
var failKeyMaps = []maps.Map{}
|
||||||
for _, result := range results {
|
if len(validateResp.FailKeys) > 0 {
|
||||||
if !result.IsOK {
|
for _, key := range validateResp.FailKeys {
|
||||||
isAllOk = false
|
failKeyMaps = append(failKeyMaps, maps.Map{
|
||||||
break
|
"key": key.Key,
|
||||||
|
"reason": cacheutils.KeyFailReason(key.ReasonCode),
|
||||||
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
this.Data["failKeys"] = failKeyMaps
|
||||||
|
if len(failKeyMaps) > 0 {
|
||||||
|
this.Fail("有" + types.String(len(failKeyMaps)) + "个Key无法完成操作,请删除后重试")
|
||||||
|
}
|
||||||
|
|
||||||
this.Data["isAllOk"] = isAllOk
|
// 提交任务
|
||||||
this.Data["results"] = results
|
_, err = this.RPC().HTTPCacheTaskRPC().CreateHTTPCacheTask(this.AdminContext(), &pb.CreateHTTPCacheTaskRequest{
|
||||||
|
Type: "fetch",
|
||||||
|
KeyType: "key",
|
||||||
|
Keys: realKeys,
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
this.ErrorPage(err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
this.Success()
|
this.Success()
|
||||||
}
|
}
|
||||||
@@ -19,7 +19,7 @@ func init() {
|
|||||||
Get("/policy", new(PolicyAction)).
|
Get("/policy", new(PolicyAction)).
|
||||||
GetPost("/update", new(UpdateAction)).
|
GetPost("/update", new(UpdateAction)).
|
||||||
GetPost("/clean", new(CleanAction)).
|
GetPost("/clean", new(CleanAction)).
|
||||||
GetPost("/preheat", new(PreheatAction)).
|
GetPost("/fetch", new(FetchAction)).
|
||||||
GetPost("/purge", new(PurgeAction)).
|
GetPost("/purge", new(PurgeAction)).
|
||||||
GetPost("/stat", new(StatAction)).
|
GetPost("/stat", new(StatAction)).
|
||||||
GetPost("/test", new(TestAction)).
|
GetPost("/test", new(TestAction)).
|
||||||
|
|||||||
@@ -3,8 +3,7 @@ package cache
|
|||||||
import (
|
import (
|
||||||
"github.com/TeaOSLab/EdgeAdmin/internal/oplogs"
|
"github.com/TeaOSLab/EdgeAdmin/internal/oplogs"
|
||||||
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
|
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
|
||||||
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/default/nodes/nodeutils"
|
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/default/servers/components/cache/cacheutils"
|
||||||
"github.com/TeaOSLab/EdgeCommon/pkg/messageconfigs"
|
|
||||||
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
|
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
|
||||||
"github.com/iwind/TeaGo/actions"
|
"github.com/iwind/TeaGo/actions"
|
||||||
"github.com/iwind/TeaGo/lists"
|
"github.com/iwind/TeaGo/lists"
|
||||||
@@ -53,7 +52,7 @@ func (this *PurgeAction) RunGet(params struct {
|
|||||||
func (this *PurgeAction) RunPost(params struct {
|
func (this *PurgeAction) RunPost(params struct {
|
||||||
CachePolicyId int64
|
CachePolicyId int64
|
||||||
ClusterId int64
|
ClusterId int64
|
||||||
Type string
|
KeyType string
|
||||||
Keys string
|
Keys string
|
||||||
Must *actions.Must
|
Must *actions.Must
|
||||||
}) {
|
}) {
|
||||||
@@ -91,33 +90,37 @@ func (this *PurgeAction) RunPost(params struct {
|
|||||||
}
|
}
|
||||||
realKeys = append(realKeys, key)
|
realKeys = append(realKeys, key)
|
||||||
}
|
}
|
||||||
|
// 校验Key
|
||||||
// 发送命令
|
validateResp, err := this.RPC().HTTPCacheTaskKeyRPC().ValidateHTTPCacheTaskKeys(this.AdminContext(), &pb.ValidateHTTPCacheTaskKeysRequest{Keys: realKeys})
|
||||||
msg := &messageconfigs.PurgeCacheMessage{
|
|
||||||
CachePolicyJSON: cachePolicyJSON,
|
|
||||||
Keys: realKeys,
|
|
||||||
}
|
|
||||||
if params.Type == "prefix" {
|
|
||||||
msg.Type = messageconfigs.PurgeCacheMessageTypeDir
|
|
||||||
} else {
|
|
||||||
msg.Type = messageconfigs.PurgeCacheMessageTypeFile
|
|
||||||
}
|
|
||||||
results, err := nodeutils.SendMessageToCluster(this.AdminContext(), params.ClusterId, messageconfigs.MessageCodePurgeCache, msg, 10)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
this.ErrorPage(err)
|
this.ErrorPage(err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
isAllOk := true
|
var failKeyMaps = []maps.Map{}
|
||||||
for _, result := range results {
|
if len(validateResp.FailKeys) > 0 {
|
||||||
if !result.IsOK {
|
for _, key := range validateResp.FailKeys {
|
||||||
isAllOk = false
|
failKeyMaps = append(failKeyMaps, maps.Map{
|
||||||
break
|
"key": key.Key,
|
||||||
|
"reason": cacheutils.KeyFailReason(key.ReasonCode),
|
||||||
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
this.Data["failKeys"] = failKeyMaps
|
||||||
|
if len(failKeyMaps) > 0 {
|
||||||
|
this.Fail("有" + types.String(len(failKeyMaps)) + "个Key无法完成操作,请删除后重试")
|
||||||
|
}
|
||||||
|
|
||||||
this.Data["isAllOk"] = isAllOk
|
// 提交任务
|
||||||
this.Data["results"] = results
|
_, err = this.RPC().HTTPCacheTaskRPC().CreateHTTPCacheTask(this.AdminContext(), &pb.CreateHTTPCacheTaskRequest{
|
||||||
|
Type: "purge",
|
||||||
|
KeyType: params.KeyType,
|
||||||
|
Keys: realKeys,
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
this.ErrorPage(err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
this.Success()
|
this.Success()
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,25 +5,26 @@ package cache
|
|||||||
import (
|
import (
|
||||||
"github.com/TeaOSLab/EdgeAdmin/internal/oplogs"
|
"github.com/TeaOSLab/EdgeAdmin/internal/oplogs"
|
||||||
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
|
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
|
||||||
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/default/nodes/nodeutils"
|
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/default/servers/components/cache/cacheutils"
|
||||||
"github.com/TeaOSLab/EdgeCommon/pkg/messageconfigs"
|
|
||||||
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/dao"
|
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/dao"
|
||||||
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
|
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
|
||||||
"github.com/iwind/TeaGo/actions"
|
"github.com/iwind/TeaGo/actions"
|
||||||
"github.com/iwind/TeaGo/lists"
|
"github.com/iwind/TeaGo/lists"
|
||||||
|
"github.com/iwind/TeaGo/maps"
|
||||||
|
"github.com/iwind/TeaGo/types"
|
||||||
"strings"
|
"strings"
|
||||||
)
|
)
|
||||||
|
|
||||||
type PreheatAction struct {
|
type FetchAction struct {
|
||||||
actionutils.ParentAction
|
actionutils.ParentAction
|
||||||
}
|
}
|
||||||
|
|
||||||
func (this *PreheatAction) Init() {
|
func (this *FetchAction) Init() {
|
||||||
this.Nav("", "setting", "preheat")
|
this.Nav("", "setting", "fetch")
|
||||||
this.SecondMenu("cache")
|
this.SecondMenu("cache")
|
||||||
}
|
}
|
||||||
|
|
||||||
func (this *PreheatAction) RunGet(params struct {
|
func (this *FetchAction) RunGet(params struct {
|
||||||
ServerId int64
|
ServerId int64
|
||||||
}) {
|
}) {
|
||||||
webConfig, err := dao.SharedHTTPWebDAO.FindWebConfigWithServerId(this.AdminContext(), params.ServerId)
|
webConfig, err := dao.SharedHTTPWebDAO.FindWebConfigWithServerId(this.AdminContext(), params.ServerId)
|
||||||
@@ -38,7 +39,7 @@ func (this *PreheatAction) RunGet(params struct {
|
|||||||
this.Show()
|
this.Show()
|
||||||
}
|
}
|
||||||
|
|
||||||
func (this *PreheatAction) RunPost(params struct {
|
func (this *FetchAction) RunPost(params struct {
|
||||||
ServerId int64
|
ServerId int64
|
||||||
WebId int64
|
WebId int64
|
||||||
Keys string
|
Keys string
|
||||||
@@ -117,27 +118,38 @@ func (this *PreheatAction) RunPost(params struct {
|
|||||||
realKeys = append(realKeys, key)
|
realKeys = append(realKeys, key)
|
||||||
}
|
}
|
||||||
|
|
||||||
// 发送命令
|
|
||||||
msg := &messageconfigs.PreheatCacheMessage{
|
// 校验Key
|
||||||
CachePolicyJSON: cachePolicyJSON,
|
validateResp, err := this.RPC().HTTPCacheTaskKeyRPC().ValidateHTTPCacheTaskKeys(this.AdminContext(), &pb.ValidateHTTPCacheTaskKeysRequest{Keys: realKeys})
|
||||||
Keys: realKeys,
|
|
||||||
}
|
|
||||||
results, err := nodeutils.SendMessageToCluster(this.AdminContext(), clusterId, messageconfigs.MessageCodePreheatCache, msg, 300)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
this.ErrorPage(err)
|
this.ErrorPage(err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
isAllOk := true
|
var failKeyMaps = []maps.Map{}
|
||||||
for _, result := range results {
|
if len(validateResp.FailKeys) > 0 {
|
||||||
if !result.IsOK {
|
for _, key := range validateResp.FailKeys {
|
||||||
isAllOk = false
|
failKeyMaps = append(failKeyMaps, maps.Map{
|
||||||
break
|
"key": key.Key,
|
||||||
|
"reason": cacheutils.KeyFailReason(key.ReasonCode),
|
||||||
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
this.Data["failKeys"] = failKeyMaps
|
||||||
|
if len(failKeyMaps) > 0 {
|
||||||
|
this.Fail("有" + types.String(len(failKeyMaps)) + "个Key无法完成操作,请删除后重试")
|
||||||
|
}
|
||||||
|
|
||||||
this.Data["isAllOk"] = isAllOk
|
// 提交任务
|
||||||
this.Data["results"] = results
|
_, err = this.RPC().HTTPCacheTaskRPC().CreateHTTPCacheTask(this.AdminContext(), &pb.CreateHTTPCacheTaskRequest{
|
||||||
|
Type: "fetch",
|
||||||
|
KeyType: "key",
|
||||||
|
Keys: realKeys,
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
this.ErrorPage(err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
this.Success()
|
this.Success()
|
||||||
}
|
}
|
||||||
@@ -15,7 +15,7 @@ func init() {
|
|||||||
Prefix("/servers/groups/group/settings/cache").
|
Prefix("/servers/groups/group/settings/cache").
|
||||||
GetPost("", new(IndexAction)).
|
GetPost("", new(IndexAction)).
|
||||||
GetPost("/purge", new(PurgeAction)).
|
GetPost("/purge", new(PurgeAction)).
|
||||||
GetPost("/preheat", new(PreheatAction)).
|
GetPost("/fetch", new(FetchAction)).
|
||||||
EndAll()
|
EndAll()
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,12 +5,13 @@ package cache
|
|||||||
import (
|
import (
|
||||||
"github.com/TeaOSLab/EdgeAdmin/internal/oplogs"
|
"github.com/TeaOSLab/EdgeAdmin/internal/oplogs"
|
||||||
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
|
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
|
||||||
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/default/nodes/nodeutils"
|
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/default/servers/components/cache/cacheutils"
|
||||||
"github.com/TeaOSLab/EdgeCommon/pkg/messageconfigs"
|
|
||||||
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/dao"
|
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/dao"
|
||||||
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
|
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
|
||||||
"github.com/iwind/TeaGo/actions"
|
"github.com/iwind/TeaGo/actions"
|
||||||
"github.com/iwind/TeaGo/lists"
|
"github.com/iwind/TeaGo/lists"
|
||||||
|
"github.com/iwind/TeaGo/maps"
|
||||||
|
"github.com/iwind/TeaGo/types"
|
||||||
"strings"
|
"strings"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -41,7 +42,7 @@ func (this *PurgeAction) RunGet(params struct {
|
|||||||
func (this *PurgeAction) RunPost(params struct {
|
func (this *PurgeAction) RunPost(params struct {
|
||||||
ServerId int64
|
ServerId int64
|
||||||
WebId int64
|
WebId int64
|
||||||
Type string
|
KeyType string
|
||||||
Keys string
|
Keys string
|
||||||
|
|
||||||
Must *actions.Must
|
Must *actions.Must
|
||||||
@@ -118,32 +119,37 @@ func (this *PurgeAction) RunPost(params struct {
|
|||||||
realKeys = append(realKeys, key)
|
realKeys = append(realKeys, key)
|
||||||
}
|
}
|
||||||
|
|
||||||
// 发送命令
|
// 校验Key
|
||||||
msg := &messageconfigs.PurgeCacheMessage{
|
validateResp, err := this.RPC().HTTPCacheTaskKeyRPC().ValidateHTTPCacheTaskKeys(this.AdminContext(), &pb.ValidateHTTPCacheTaskKeysRequest{Keys: realKeys})
|
||||||
CachePolicyJSON: cachePolicyJSON,
|
|
||||||
Keys: realKeys,
|
|
||||||
}
|
|
||||||
if params.Type == "prefix" {
|
|
||||||
msg.Type = messageconfigs.PurgeCacheMessageTypeDir
|
|
||||||
} else {
|
|
||||||
msg.Type = messageconfigs.PurgeCacheMessageTypeFile
|
|
||||||
}
|
|
||||||
results, err := nodeutils.SendMessageToCluster(this.AdminContext(), clusterId, messageconfigs.MessageCodePurgeCache, msg, 10)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
this.ErrorPage(err)
|
this.ErrorPage(err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
isAllOk := true
|
var failKeyMaps = []maps.Map{}
|
||||||
for _, result := range results {
|
if len(validateResp.FailKeys) > 0 {
|
||||||
if !result.IsOK {
|
for _, key := range validateResp.FailKeys {
|
||||||
isAllOk = false
|
failKeyMaps = append(failKeyMaps, maps.Map{
|
||||||
break
|
"key": key.Key,
|
||||||
|
"reason": cacheutils.KeyFailReason(key.ReasonCode),
|
||||||
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
this.Data["failKeys"] = failKeyMaps
|
||||||
|
if len(failKeyMaps) > 0 {
|
||||||
|
this.Fail("有" + types.String(len(failKeyMaps)) + "个Key无法完成操作,请删除后重试")
|
||||||
|
}
|
||||||
|
|
||||||
this.Data["isAllOk"] = isAllOk
|
// 提交任务
|
||||||
this.Data["results"] = results
|
_, err = this.RPC().HTTPCacheTaskRPC().CreateHTTPCacheTask(this.AdminContext(), &pb.CreateHTTPCacheTaskRequest{
|
||||||
|
Type: "purge",
|
||||||
|
KeyType: params.KeyType,
|
||||||
|
Keys: realKeys,
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
this.ErrorPage(err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
this.Success()
|
this.Success()
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,25 +5,26 @@ package cache
|
|||||||
import (
|
import (
|
||||||
"github.com/TeaOSLab/EdgeAdmin/internal/oplogs"
|
"github.com/TeaOSLab/EdgeAdmin/internal/oplogs"
|
||||||
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
|
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
|
||||||
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/default/nodes/nodeutils"
|
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/default/servers/components/cache/cacheutils"
|
||||||
"github.com/TeaOSLab/EdgeCommon/pkg/messageconfigs"
|
|
||||||
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/dao"
|
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/dao"
|
||||||
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
|
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
|
||||||
"github.com/iwind/TeaGo/actions"
|
"github.com/iwind/TeaGo/actions"
|
||||||
"github.com/iwind/TeaGo/lists"
|
"github.com/iwind/TeaGo/lists"
|
||||||
|
"github.com/iwind/TeaGo/maps"
|
||||||
|
"github.com/iwind/TeaGo/types"
|
||||||
"strings"
|
"strings"
|
||||||
)
|
)
|
||||||
|
|
||||||
type PreheatAction struct {
|
type FetchAction struct {
|
||||||
actionutils.ParentAction
|
actionutils.ParentAction
|
||||||
}
|
}
|
||||||
|
|
||||||
func (this *PreheatAction) Init() {
|
func (this *FetchAction) Init() {
|
||||||
this.Nav("", "setting", "preheat")
|
this.Nav("", "setting", "fetch")
|
||||||
this.SecondMenu("cache")
|
this.SecondMenu("cache")
|
||||||
}
|
}
|
||||||
|
|
||||||
func (this *PreheatAction) RunGet(params struct {
|
func (this *FetchAction) RunGet(params struct {
|
||||||
ServerId int64
|
ServerId int64
|
||||||
}) {
|
}) {
|
||||||
webConfig, err := dao.SharedHTTPWebDAO.FindWebConfigWithServerId(this.AdminContext(), params.ServerId)
|
webConfig, err := dao.SharedHTTPWebDAO.FindWebConfigWithServerId(this.AdminContext(), params.ServerId)
|
||||||
@@ -38,7 +39,7 @@ func (this *PreheatAction) RunGet(params struct {
|
|||||||
this.Show()
|
this.Show()
|
||||||
}
|
}
|
||||||
|
|
||||||
func (this *PreheatAction) RunPost(params struct {
|
func (this *FetchAction) RunPost(params struct {
|
||||||
ServerId int64
|
ServerId int64
|
||||||
WebId int64
|
WebId int64
|
||||||
Keys string
|
Keys string
|
||||||
@@ -117,27 +118,37 @@ func (this *PreheatAction) RunPost(params struct {
|
|||||||
realKeys = append(realKeys, key)
|
realKeys = append(realKeys, key)
|
||||||
}
|
}
|
||||||
|
|
||||||
// 发送命令
|
// 校验Key
|
||||||
msg := &messageconfigs.PreheatCacheMessage{
|
validateResp, err := this.RPC().HTTPCacheTaskKeyRPC().ValidateHTTPCacheTaskKeys(this.AdminContext(), &pb.ValidateHTTPCacheTaskKeysRequest{Keys: realKeys})
|
||||||
CachePolicyJSON: cachePolicyJSON,
|
|
||||||
Keys: realKeys,
|
|
||||||
}
|
|
||||||
results, err := nodeutils.SendMessageToCluster(this.AdminContext(), clusterId, messageconfigs.MessageCodePreheatCache, msg, 300)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
this.ErrorPage(err)
|
this.ErrorPage(err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
isAllOk := true
|
var failKeyMaps = []maps.Map{}
|
||||||
for _, result := range results {
|
if len(validateResp.FailKeys) > 0 {
|
||||||
if !result.IsOK {
|
for _, key := range validateResp.FailKeys {
|
||||||
isAllOk = false
|
failKeyMaps = append(failKeyMaps, maps.Map{
|
||||||
break
|
"key": key.Key,
|
||||||
|
"reason": cacheutils.KeyFailReason(key.ReasonCode),
|
||||||
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
this.Data["failKeys"] = failKeyMaps
|
||||||
|
if len(failKeyMaps) > 0 {
|
||||||
|
this.Fail("有" + types.String(len(failKeyMaps)) + "个Key无法完成操作,请删除后重试")
|
||||||
|
}
|
||||||
|
|
||||||
this.Data["isAllOk"] = isAllOk
|
// 提交任务
|
||||||
this.Data["results"] = results
|
_, err = this.RPC().HTTPCacheTaskRPC().CreateHTTPCacheTask(this.AdminContext(), &pb.CreateHTTPCacheTaskRequest{
|
||||||
|
Type: "fetch",
|
||||||
|
KeyType: "key",
|
||||||
|
Keys: realKeys,
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
this.ErrorPage(err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
this.Success()
|
this.Success()
|
||||||
}
|
}
|
||||||
@@ -16,7 +16,7 @@ func init() {
|
|||||||
GetPost("", new(IndexAction)).
|
GetPost("", new(IndexAction)).
|
||||||
GetPost("/createPopup", new(CreatePopupAction)).
|
GetPost("/createPopup", new(CreatePopupAction)).
|
||||||
GetPost("/purge", new(PurgeAction)).
|
GetPost("/purge", new(PurgeAction)).
|
||||||
GetPost("/preheat", new(PreheatAction)).
|
GetPost("/fetch", new(FetchAction)).
|
||||||
Post("/updateRefs", new(UpdateRefsAction)).
|
Post("/updateRefs", new(UpdateRefsAction)).
|
||||||
EndAll()
|
EndAll()
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -5,12 +5,13 @@ package cache
|
|||||||
import (
|
import (
|
||||||
"github.com/TeaOSLab/EdgeAdmin/internal/oplogs"
|
"github.com/TeaOSLab/EdgeAdmin/internal/oplogs"
|
||||||
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
|
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
|
||||||
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/default/nodes/nodeutils"
|
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/default/servers/components/cache/cacheutils"
|
||||||
"github.com/TeaOSLab/EdgeCommon/pkg/messageconfigs"
|
|
||||||
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/dao"
|
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/dao"
|
||||||
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
|
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
|
||||||
"github.com/iwind/TeaGo/actions"
|
"github.com/iwind/TeaGo/actions"
|
||||||
"github.com/iwind/TeaGo/lists"
|
"github.com/iwind/TeaGo/lists"
|
||||||
|
"github.com/iwind/TeaGo/maps"
|
||||||
|
"github.com/iwind/TeaGo/types"
|
||||||
"strings"
|
"strings"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -41,7 +42,7 @@ func (this *PurgeAction) RunGet(params struct {
|
|||||||
func (this *PurgeAction) RunPost(params struct {
|
func (this *PurgeAction) RunPost(params struct {
|
||||||
ServerId int64
|
ServerId int64
|
||||||
WebId int64
|
WebId int64
|
||||||
Type string
|
KeyType string
|
||||||
Keys string
|
Keys string
|
||||||
|
|
||||||
Must *actions.Must
|
Must *actions.Must
|
||||||
@@ -118,32 +119,37 @@ func (this *PurgeAction) RunPost(params struct {
|
|||||||
realKeys = append(realKeys, key)
|
realKeys = append(realKeys, key)
|
||||||
}
|
}
|
||||||
|
|
||||||
// 发送命令
|
// 校验Key
|
||||||
msg := &messageconfigs.PurgeCacheMessage{
|
validateResp, err := this.RPC().HTTPCacheTaskKeyRPC().ValidateHTTPCacheTaskKeys(this.AdminContext(), &pb.ValidateHTTPCacheTaskKeysRequest{Keys: realKeys})
|
||||||
CachePolicyJSON: cachePolicyJSON,
|
|
||||||
Keys: realKeys,
|
|
||||||
}
|
|
||||||
if params.Type == "prefix" {
|
|
||||||
msg.Type = messageconfigs.PurgeCacheMessageTypeDir
|
|
||||||
} else {
|
|
||||||
msg.Type = messageconfigs.PurgeCacheMessageTypeFile
|
|
||||||
}
|
|
||||||
results, err := nodeutils.SendMessageToCluster(this.AdminContext(), clusterId, messageconfigs.MessageCodePurgeCache, msg, 10)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
this.ErrorPage(err)
|
this.ErrorPage(err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
isAllOk := true
|
var failKeyMaps = []maps.Map{}
|
||||||
for _, result := range results {
|
if len(validateResp.FailKeys) > 0 {
|
||||||
if !result.IsOK {
|
for _, key := range validateResp.FailKeys {
|
||||||
isAllOk = false
|
failKeyMaps = append(failKeyMaps, maps.Map{
|
||||||
break
|
"key": key.Key,
|
||||||
|
"reason": cacheutils.KeyFailReason(key.ReasonCode),
|
||||||
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
this.Data["failKeys"] = failKeyMaps
|
||||||
|
if len(failKeyMaps) > 0 {
|
||||||
|
this.Fail("有" + types.String(len(failKeyMaps)) + "个Key无法完成操作,请删除后重试")
|
||||||
|
}
|
||||||
|
|
||||||
this.Data["isAllOk"] = isAllOk
|
// 提交任务
|
||||||
this.Data["results"] = results
|
_, err = this.RPC().HTTPCacheTaskRPC().CreateHTTPCacheTask(this.AdminContext(), &pb.CreateHTTPCacheTaskRequest{
|
||||||
|
Type: "purge",
|
||||||
|
KeyType: params.KeyType,
|
||||||
|
Keys: realKeys,
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
this.ErrorPage(err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
this.Success()
|
this.Success()
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -34,11 +34,26 @@ func FindAllMenuMaps(nodeLogsType string, countUnreadNodeLogs int64, countUnread
|
|||||||
"url": "/servers/certs",
|
"url": "/servers/certs",
|
||||||
"code": "cert",
|
"code": "cert",
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"name": "服务分组",
|
||||||
|
"url": "/servers/groups",
|
||||||
|
"code": "group",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "-",
|
||||||
|
"url": "",
|
||||||
|
"code": "",
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"name": "缓存策略",
|
"name": "缓存策略",
|
||||||
"url": "/servers/components/cache",
|
"url": "/servers/components/cache",
|
||||||
"code": "cache",
|
"code": "cache",
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"name": "刷新预热",
|
||||||
|
"url": "/servers/components/cache/batch",
|
||||||
|
"code": "cacheBatch",
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"name": "-",
|
"name": "-",
|
||||||
"url": "",
|
"url": "",
|
||||||
@@ -60,11 +75,6 @@ func FindAllMenuMaps(nodeLogsType string, countUnreadNodeLogs int64, countUnread
|
|||||||
"url": "",
|
"url": "",
|
||||||
"code": "",
|
"code": "",
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"name": "服务分组",
|
|
||||||
"url": "/servers/groups",
|
|
||||||
"code": "group",
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"name": "统计指标",
|
"name": "统计指标",
|
||||||
"url": "/servers/metrics",
|
"url": "/servers/metrics",
|
||||||
|
|||||||
@@ -333,7 +333,7 @@ Vue.component("traffic-map-box",{props:["v-stats","v-is-attack"],mounted:functio
|
|||||||
<table class="ui table definition selectable">
|
<table class="ui table definition selectable">
|
||||||
<tbody>
|
<tbody>
|
||||||
<tr>
|
<tr>
|
||||||
<td class="title">是否启用</td>
|
<td class="title">启用</td>
|
||||||
<td>
|
<td>
|
||||||
<div class="ui checkbox">
|
<div class="ui checkbox">
|
||||||
<input type="checkbox" name="isOn" value="1" v-model="config.isOn"/>
|
<input type="checkbox" name="isOn" value="1" v-model="config.isOn"/>
|
||||||
@@ -402,7 +402,7 @@ Vue.component("traffic-map-box",{props:["v-stats","v-is-attack"],mounted:functio
|
|||||||
<prior-checkbox :v-config="config" v-if="!vIsParent"></prior-checkbox>
|
<prior-checkbox :v-config="config" v-if="!vIsParent"></prior-checkbox>
|
||||||
<tbody v-show="vIsParent || config.isPrior">
|
<tbody v-show="vIsParent || config.isPrior">
|
||||||
<tr>
|
<tr>
|
||||||
<td class="title">是否启用</td>
|
<td class="title">启用</td>
|
||||||
<td>
|
<td>
|
||||||
<checkbox name="isOn" value="1" v-model="config.isOn"></checkbox>
|
<checkbox name="isOn" value="1" v-model="config.isOn"></checkbox>
|
||||||
</td>
|
</td>
|
||||||
@@ -1356,7 +1356,7 @@ Vue.component("traffic-map-box",{props:["v-stats","v-is-attack"],mounted:functio
|
|||||||
<td class="color-border">PURGE Key *</td>
|
<td class="color-border">PURGE Key *</td>
|
||||||
<td>
|
<td>
|
||||||
<input type="text" maxlength="200" v-model="cacheConfig.purgeKey"/>
|
<input type="text" maxlength="200" v-model="cacheConfig.purgeKey"/>
|
||||||
<p class="comment"><a href="" @click.prevent="generatePurgeKey">[随机生成]</a>。需要在PURGE方法调用时加入<code-label>Edge-Purge-Key: {{cacheConfig.purgeKey}}</code-label> Header。只能包含字符、数字、下划线。</p>
|
<p class="comment"><a href="" @click.prevent="generatePurgeKey">[随机生成]</a>。需要在PURGE方法调用时加入<code-label>X-Edge-Purge-Key: {{cacheConfig.purgeKey}}</code-label> Header。只能包含字符、数字、下划线。</p>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
</tbody>
|
</tbody>
|
||||||
@@ -1552,7 +1552,7 @@ Vue.component("traffic-map-box",{props:["v-stats","v-is-attack"],mounted:functio
|
|||||||
<prior-checkbox :v-config="websocketRef" v-if="vIsLocation || vIsGroup"></prior-checkbox>
|
<prior-checkbox :v-config="websocketRef" v-if="vIsLocation || vIsGroup"></prior-checkbox>
|
||||||
<tbody v-show="((!vIsLocation && !vIsGroup) || websocketRef.isPrior)">
|
<tbody v-show="((!vIsLocation && !vIsGroup) || websocketRef.isPrior)">
|
||||||
<tr>
|
<tr>
|
||||||
<td class="title">是否启用配置</td>
|
<td class="title">启用配置</td>
|
||||||
<td>
|
<td>
|
||||||
<div class="ui checkbox">
|
<div class="ui checkbox">
|
||||||
<input type="checkbox" v-model="websocketRef.isOn"/>
|
<input type="checkbox" v-model="websocketRef.isOn"/>
|
||||||
@@ -2356,7 +2356,7 @@ Vue.component("traffic-map-box",{props:["v-stats","v-is-attack"],mounted:functio
|
|||||||
<prior-checkbox :v-config="shutdownConfig" v-if="vIsLocation"></prior-checkbox>
|
<prior-checkbox :v-config="shutdownConfig" v-if="vIsLocation"></prior-checkbox>
|
||||||
<tbody v-show="!vIsLocation || shutdownConfig.isPrior">
|
<tbody v-show="!vIsLocation || shutdownConfig.isPrior">
|
||||||
<tr>
|
<tr>
|
||||||
<td class="title">是否开启</td>
|
<td class="title">开启</td>
|
||||||
<td>
|
<td>
|
||||||
<div class="ui checkbox">
|
<div class="ui checkbox">
|
||||||
<input type="checkbox" value="1" v-model="shutdownConfig.isOn" />
|
<input type="checkbox" value="1" v-model="shutdownConfig.isOn" />
|
||||||
@@ -2407,7 +2407,7 @@ Vue.component("traffic-map-box",{props:["v-stats","v-is-attack"],mounted:functio
|
|||||||
<prior-checkbox :v-config="config" v-if="vIsLocation || vIsGroup"></prior-checkbox>
|
<prior-checkbox :v-config="config" v-if="vIsLocation || vIsGroup"></prior-checkbox>
|
||||||
<tbody v-show="(!vIsLocation && !vIsGroup) || config.isPrior">
|
<tbody v-show="(!vIsLocation && !vIsGroup) || config.isPrior">
|
||||||
<tr>
|
<tr>
|
||||||
<td class="title">是否启用</td>
|
<td class="title">启用</td>
|
||||||
<td>
|
<td>
|
||||||
<div class="ui checkbox">
|
<div class="ui checkbox">
|
||||||
<input type="checkbox" value="1" v-model="config.isOn"/>
|
<input type="checkbox" value="1" v-model="config.isOn"/>
|
||||||
@@ -2516,7 +2516,7 @@ Vue.component("traffic-map-box",{props:["v-stats","v-is-attack"],mounted:functio
|
|||||||
<prior-checkbox :v-config="charsetConfig" v-if="vIsLocation || vIsGroup"></prior-checkbox>
|
<prior-checkbox :v-config="charsetConfig" v-if="vIsLocation || vIsGroup"></prior-checkbox>
|
||||||
<tbody v-show="(!vIsLocation && !vIsGroup) || charsetConfig.isPrior">
|
<tbody v-show="(!vIsLocation && !vIsGroup) || charsetConfig.isPrior">
|
||||||
<tr>
|
<tr>
|
||||||
<td class="title">是否启用</td>
|
<td class="title">启用</td>
|
||||||
<td>
|
<td>
|
||||||
<div class="ui checkbox">
|
<div class="ui checkbox">
|
||||||
<input type="checkbox" v-model="charsetConfig.isOn"/>
|
<input type="checkbox" v-model="charsetConfig.isOn"/>
|
||||||
@@ -2558,7 +2558,7 @@ Vue.component("traffic-map-box",{props:["v-stats","v-is-attack"],mounted:functio
|
|||||||
<prior-checkbox :v-config="expiresTime"></prior-checkbox>
|
<prior-checkbox :v-config="expiresTime"></prior-checkbox>
|
||||||
<tbody v-show="expiresTime.isPrior">
|
<tbody v-show="expiresTime.isPrior">
|
||||||
<tr>
|
<tr>
|
||||||
<td class="title">是否启用</td>
|
<td class="title">启用</td>
|
||||||
<td><checkbox v-model="expiresTime.isOn"></checkbox>
|
<td><checkbox v-model="expiresTime.isOn"></checkbox>
|
||||||
<p class="comment">启用后,将会在响应的Header中添加<code-label>Expires</code-label>字段,浏览器据此会将内容缓存在客户端;同时,在管理后台执行清理缓存时,也将无法清理客户端已有的缓存。</p>
|
<p class="comment">启用后,将会在响应的Header中添加<code-label>Expires</code-label>字段,浏览器据此会将内容缓存在客户端;同时,在管理后台执行清理缓存时,也将无法清理客户端已有的缓存。</p>
|
||||||
</td>
|
</td>
|
||||||
@@ -2872,7 +2872,7 @@ Vue.component("traffic-map-box",{props:["v-stats","v-is-attack"],mounted:functio
|
|||||||
<prior-checkbox :v-config="reverseProxyRef" v-if="vIsLocation || vIsGroup"></prior-checkbox>
|
<prior-checkbox :v-config="reverseProxyRef" v-if="vIsLocation || vIsGroup"></prior-checkbox>
|
||||||
<tbody v-show="(!vIsLocation && !vIsGroup) || reverseProxyRef.isPrior">
|
<tbody v-show="(!vIsLocation && !vIsGroup) || reverseProxyRef.isPrior">
|
||||||
<tr>
|
<tr>
|
||||||
<td class="title">是否启用反向代理</td>
|
<td class="title">启用反向代理</td>
|
||||||
<td>
|
<td>
|
||||||
<div class="ui checkbox">
|
<div class="ui checkbox">
|
||||||
<input type="checkbox" v-model="reverseProxyRef.isOn"/>
|
<input type="checkbox" v-model="reverseProxyRef.isOn"/>
|
||||||
@@ -3377,7 +3377,7 @@ Vue.component("traffic-map-box",{props:["v-stats","v-is-attack"],mounted:functio
|
|||||||
<prior-checkbox :v-config="fastcgiRef" v-if="vIsLocation"></prior-checkbox>
|
<prior-checkbox :v-config="fastcgiRef" v-if="vIsLocation"></prior-checkbox>
|
||||||
<tbody v-show="(!this.vIsLocation || this.fastcgiRef.isPrior)">
|
<tbody v-show="(!this.vIsLocation || this.fastcgiRef.isPrior)">
|
||||||
<tr>
|
<tr>
|
||||||
<td class="title">是否启用配置</td>
|
<td class="title">启用配置</td>
|
||||||
<td>
|
<td>
|
||||||
<div class="ui checkbox">
|
<div class="ui checkbox">
|
||||||
<input type="checkbox" v-model="fastcgiRef.isOn"/>
|
<input type="checkbox" v-model="fastcgiRef.isOn"/>
|
||||||
@@ -3868,7 +3868,7 @@ Vue.component("traffic-map-box",{props:["v-stats","v-is-attack"],mounted:functio
|
|||||||
|
|
||||||
<table class="ui table selectable" v-show="isEditing">
|
<table class="ui table selectable" v-show="isEditing">
|
||||||
<tr>
|
<tr>
|
||||||
<td class="title">是否启用</td>
|
<td class="title">启用</td>
|
||||||
<td>
|
<td>
|
||||||
<checkbox v-model="config.isOn"></checkbox>
|
<checkbox v-model="config.isOn"></checkbox>
|
||||||
<p class="comment">启用后,WAF将会尝试自动检测并阻止SYN Flood攻击。此功能需要节点已安装并启用Firewalld。</p>
|
<p class="comment">启用后,WAF将会尝试自动检测并阻止SYN Flood攻击。此功能需要节点已安装并启用Firewalld。</p>
|
||||||
@@ -4178,7 +4178,7 @@ Vue.component("traffic-map-box",{props:["v-stats","v-is-attack"],mounted:functio
|
|||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td>是否自动下线</td>
|
<td>自动下线</td>
|
||||||
<td>
|
<td>
|
||||||
<div class="ui checkbox">
|
<div class="ui checkbox">
|
||||||
<input type="checkbox" value="1" v-model="healthCheck.autoDown"/>
|
<input type="checkbox" value="1" v-model="healthCheck.autoDown"/>
|
||||||
|
|||||||
@@ -1318,7 +1318,7 @@ Vue.component("ns-recursion-config-box", {
|
|||||||
<table class="ui table definition selectable">
|
<table class="ui table definition selectable">
|
||||||
<tbody>
|
<tbody>
|
||||||
<tr>
|
<tr>
|
||||||
<td class="title">是否启用</td>
|
<td class="title">启用</td>
|
||||||
<td>
|
<td>
|
||||||
<div class="ui checkbox">
|
<div class="ui checkbox">
|
||||||
<input type="checkbox" name="isOn" value="1" v-model="config.isOn"/>
|
<input type="checkbox" name="isOn" value="1" v-model="config.isOn"/>
|
||||||
@@ -1408,7 +1408,7 @@ Vue.component("ns-access-log-ref-box", {
|
|||||||
<prior-checkbox :v-config="config" v-if="!vIsParent"></prior-checkbox>
|
<prior-checkbox :v-config="config" v-if="!vIsParent"></prior-checkbox>
|
||||||
<tbody v-show="vIsParent || config.isPrior">
|
<tbody v-show="vIsParent || config.isPrior">
|
||||||
<tr>
|
<tr>
|
||||||
<td class="title">是否启用</td>
|
<td class="title">启用</td>
|
||||||
<td>
|
<td>
|
||||||
<checkbox name="isOn" value="1" v-model="config.isOn"></checkbox>
|
<checkbox name="isOn" value="1" v-model="config.isOn"></checkbox>
|
||||||
</td>
|
</td>
|
||||||
@@ -4250,7 +4250,7 @@ Vue.component("http-cache-config-box", {
|
|||||||
<td class="color-border">PURGE Key *</td>
|
<td class="color-border">PURGE Key *</td>
|
||||||
<td>
|
<td>
|
||||||
<input type="text" maxlength="200" v-model="cacheConfig.purgeKey"/>
|
<input type="text" maxlength="200" v-model="cacheConfig.purgeKey"/>
|
||||||
<p class="comment"><a href="" @click.prevent="generatePurgeKey">[随机生成]</a>。需要在PURGE方法调用时加入<code-label>Edge-Purge-Key: {{cacheConfig.purgeKey}}</code-label> Header。只能包含字符、数字、下划线。</p>
|
<p class="comment"><a href="" @click.prevent="generatePurgeKey">[随机生成]</a>。需要在PURGE方法调用时加入<code-label>X-Edge-Purge-Key: {{cacheConfig.purgeKey}}</code-label> Header。只能包含字符、数字、下划线。</p>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
</tbody>
|
</tbody>
|
||||||
@@ -5089,7 +5089,7 @@ Vue.component("http-websocket-box", {
|
|||||||
<prior-checkbox :v-config="websocketRef" v-if="vIsLocation || vIsGroup"></prior-checkbox>
|
<prior-checkbox :v-config="websocketRef" v-if="vIsLocation || vIsGroup"></prior-checkbox>
|
||||||
<tbody v-show="((!vIsLocation && !vIsGroup) || websocketRef.isPrior)">
|
<tbody v-show="((!vIsLocation && !vIsGroup) || websocketRef.isPrior)">
|
||||||
<tr>
|
<tr>
|
||||||
<td class="title">是否启用配置</td>
|
<td class="title">启用配置</td>
|
||||||
<td>
|
<td>
|
||||||
<div class="ui checkbox">
|
<div class="ui checkbox">
|
||||||
<input type="checkbox" v-model="websocketRef.isOn"/>
|
<input type="checkbox" v-model="websocketRef.isOn"/>
|
||||||
@@ -7096,7 +7096,7 @@ Vue.component("http-pages-and-shutdown-box", {
|
|||||||
<prior-checkbox :v-config="shutdownConfig" v-if="vIsLocation"></prior-checkbox>
|
<prior-checkbox :v-config="shutdownConfig" v-if="vIsLocation"></prior-checkbox>
|
||||||
<tbody v-show="!vIsLocation || shutdownConfig.isPrior">
|
<tbody v-show="!vIsLocation || shutdownConfig.isPrior">
|
||||||
<tr>
|
<tr>
|
||||||
<td class="title">是否开启</td>
|
<td class="title">开启</td>
|
||||||
<td>
|
<td>
|
||||||
<div class="ui checkbox">
|
<div class="ui checkbox">
|
||||||
<input type="checkbox" value="1" v-model="shutdownConfig.isOn" />
|
<input type="checkbox" value="1" v-model="shutdownConfig.isOn" />
|
||||||
@@ -7294,7 +7294,7 @@ Vue.component("http-compression-config-box", {
|
|||||||
<prior-checkbox :v-config="config" v-if="vIsLocation || vIsGroup"></prior-checkbox>
|
<prior-checkbox :v-config="config" v-if="vIsLocation || vIsGroup"></prior-checkbox>
|
||||||
<tbody v-show="(!vIsLocation && !vIsGroup) || config.isPrior">
|
<tbody v-show="(!vIsLocation && !vIsGroup) || config.isPrior">
|
||||||
<tr>
|
<tr>
|
||||||
<td class="title">是否启用</td>
|
<td class="title">启用</td>
|
||||||
<td>
|
<td>
|
||||||
<div class="ui checkbox">
|
<div class="ui checkbox">
|
||||||
<input type="checkbox" value="1" v-model="config.isOn"/>
|
<input type="checkbox" value="1" v-model="config.isOn"/>
|
||||||
@@ -7489,7 +7489,7 @@ Vue.component("http-charsets-box", {
|
|||||||
<prior-checkbox :v-config="charsetConfig" v-if="vIsLocation || vIsGroup"></prior-checkbox>
|
<prior-checkbox :v-config="charsetConfig" v-if="vIsLocation || vIsGroup"></prior-checkbox>
|
||||||
<tbody v-show="(!vIsLocation && !vIsGroup) || charsetConfig.isPrior">
|
<tbody v-show="(!vIsLocation && !vIsGroup) || charsetConfig.isPrior">
|
||||||
<tr>
|
<tr>
|
||||||
<td class="title">是否启用</td>
|
<td class="title">启用</td>
|
||||||
<td>
|
<td>
|
||||||
<div class="ui checkbox">
|
<div class="ui checkbox">
|
||||||
<input type="checkbox" v-model="charsetConfig.isOn"/>
|
<input type="checkbox" v-model="charsetConfig.isOn"/>
|
||||||
@@ -7570,7 +7570,7 @@ Vue.component("http-expires-time-config-box", {
|
|||||||
<prior-checkbox :v-config="expiresTime"></prior-checkbox>
|
<prior-checkbox :v-config="expiresTime"></prior-checkbox>
|
||||||
<tbody v-show="expiresTime.isPrior">
|
<tbody v-show="expiresTime.isPrior">
|
||||||
<tr>
|
<tr>
|
||||||
<td class="title">是否启用</td>
|
<td class="title">启用</td>
|
||||||
<td><checkbox v-model="expiresTime.isOn"></checkbox>
|
<td><checkbox v-model="expiresTime.isOn"></checkbox>
|
||||||
<p class="comment">启用后,将会在响应的Header中添加<code-label>Expires</code-label>字段,浏览器据此会将内容缓存在客户端;同时,在管理后台执行清理缓存时,也将无法清理客户端已有的缓存。</p>
|
<p class="comment">启用后,将会在响应的Header中添加<code-label>Expires</code-label>字段,浏览器据此会将内容缓存在客户端;同时,在管理后台执行清理缓存时,也将无法清理客户端已有的缓存。</p>
|
||||||
</td>
|
</td>
|
||||||
@@ -8431,7 +8431,7 @@ Vue.component("reverse-proxy-box", {
|
|||||||
<prior-checkbox :v-config="reverseProxyRef" v-if="vIsLocation || vIsGroup"></prior-checkbox>
|
<prior-checkbox :v-config="reverseProxyRef" v-if="vIsLocation || vIsGroup"></prior-checkbox>
|
||||||
<tbody v-show="(!vIsLocation && !vIsGroup) || reverseProxyRef.isPrior">
|
<tbody v-show="(!vIsLocation && !vIsGroup) || reverseProxyRef.isPrior">
|
||||||
<tr>
|
<tr>
|
||||||
<td class="title">是否启用反向代理</td>
|
<td class="title">启用反向代理</td>
|
||||||
<td>
|
<td>
|
||||||
<div class="ui checkbox">
|
<div class="ui checkbox">
|
||||||
<input type="checkbox" v-model="reverseProxyRef.isOn"/>
|
<input type="checkbox" v-model="reverseProxyRef.isOn"/>
|
||||||
@@ -9548,7 +9548,7 @@ Vue.component("http-fastcgi-box", {
|
|||||||
<prior-checkbox :v-config="fastcgiRef" v-if="vIsLocation"></prior-checkbox>
|
<prior-checkbox :v-config="fastcgiRef" v-if="vIsLocation"></prior-checkbox>
|
||||||
<tbody v-show="(!this.vIsLocation || this.fastcgiRef.isPrior)">
|
<tbody v-show="(!this.vIsLocation || this.fastcgiRef.isPrior)">
|
||||||
<tr>
|
<tr>
|
||||||
<td class="title">是否启用配置</td>
|
<td class="title">启用配置</td>
|
||||||
<td>
|
<td>
|
||||||
<div class="ui checkbox">
|
<div class="ui checkbox">
|
||||||
<input type="checkbox" v-model="fastcgiRef.isOn"/>
|
<input type="checkbox" v-model="fastcgiRef.isOn"/>
|
||||||
@@ -11063,7 +11063,7 @@ Vue.component("firewall-syn-flood-config-box", {
|
|||||||
|
|
||||||
<table class="ui table selectable" v-show="isEditing">
|
<table class="ui table selectable" v-show="isEditing">
|
||||||
<tr>
|
<tr>
|
||||||
<td class="title">是否启用</td>
|
<td class="title">启用</td>
|
||||||
<td>
|
<td>
|
||||||
<checkbox v-model="config.isOn"></checkbox>
|
<checkbox v-model="config.isOn"></checkbox>
|
||||||
<p class="comment">启用后,WAF将会尝试自动检测并阻止SYN Flood攻击。此功能需要节点已安装并启用Firewalld。</p>
|
<p class="comment">启用后,WAF将会尝试自动检测并阻止SYN Flood攻击。此功能需要节点已安装并启用Firewalld。</p>
|
||||||
@@ -12675,7 +12675,7 @@ Vue.component("health-check-config-box", {
|
|||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td>是否自动下线</td>
|
<td>自动下线</td>
|
||||||
<td>
|
<td>
|
||||||
<div class="ui checkbox">
|
<div class="ui checkbox">
|
||||||
<input type="checkbox" value="1" v-model="healthCheck.autoDown"/>
|
<input type="checkbox" value="1" v-model="healthCheck.autoDown"/>
|
||||||
|
|||||||
@@ -215,7 +215,7 @@ Vue.component("health-check-config-box", {
|
|||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td>是否自动下线</td>
|
<td>自动下线</td>
|
||||||
<td>
|
<td>
|
||||||
<div class="ui checkbox">
|
<div class="ui checkbox">
|
||||||
<input type="checkbox" value="1" v-model="healthCheck.autoDown"/>
|
<input type="checkbox" value="1" v-model="healthCheck.autoDown"/>
|
||||||
|
|||||||
@@ -22,7 +22,7 @@ Vue.component("ns-access-log-ref-box", {
|
|||||||
<prior-checkbox :v-config="config" v-if="!vIsParent"></prior-checkbox>
|
<prior-checkbox :v-config="config" v-if="!vIsParent"></prior-checkbox>
|
||||||
<tbody v-show="vIsParent || config.isPrior">
|
<tbody v-show="vIsParent || config.isPrior">
|
||||||
<tr>
|
<tr>
|
||||||
<td class="title">是否启用</td>
|
<td class="title">启用</td>
|
||||||
<td>
|
<td>
|
||||||
<checkbox name="isOn" value="1" v-model="config.isOn"></checkbox>
|
<checkbox name="isOn" value="1" v-model="config.isOn"></checkbox>
|
||||||
</td>
|
</td>
|
||||||
|
|||||||
@@ -98,7 +98,7 @@ Vue.component("ns-recursion-config-box", {
|
|||||||
<table class="ui table definition selectable">
|
<table class="ui table definition selectable">
|
||||||
<tbody>
|
<tbody>
|
||||||
<tr>
|
<tr>
|
||||||
<td class="title">是否启用</td>
|
<td class="title">启用</td>
|
||||||
<td>
|
<td>
|
||||||
<div class="ui checkbox">
|
<div class="ui checkbox">
|
||||||
<input type="checkbox" name="isOn" value="1" v-model="config.isOn"/>
|
<input type="checkbox" name="isOn" value="1" v-model="config.isOn"/>
|
||||||
|
|||||||
@@ -56,7 +56,7 @@ Vue.component("firewall-syn-flood-config-box", {
|
|||||||
|
|
||||||
<table class="ui table selectable" v-show="isEditing">
|
<table class="ui table selectable" v-show="isEditing">
|
||||||
<tr>
|
<tr>
|
||||||
<td class="title">是否启用</td>
|
<td class="title">启用</td>
|
||||||
<td>
|
<td>
|
||||||
<checkbox v-model="config.isOn"></checkbox>
|
<checkbox v-model="config.isOn"></checkbox>
|
||||||
<p class="comment">启用后,WAF将会尝试自动检测并阻止SYN Flood攻击。此功能需要节点已安装并启用Firewalld。</p>
|
<p class="comment">启用后,WAF将会尝试自动检测并阻止SYN Flood攻击。此功能需要节点已安装并启用Firewalld。</p>
|
||||||
|
|||||||
@@ -125,7 +125,7 @@ Vue.component("http-cache-config-box", {
|
|||||||
<td class="color-border">PURGE Key *</td>
|
<td class="color-border">PURGE Key *</td>
|
||||||
<td>
|
<td>
|
||||||
<input type="text" maxlength="200" v-model="cacheConfig.purgeKey"/>
|
<input type="text" maxlength="200" v-model="cacheConfig.purgeKey"/>
|
||||||
<p class="comment"><a href="" @click.prevent="generatePurgeKey">[随机生成]</a>。需要在PURGE方法调用时加入<code-label>Edge-Purge-Key: {{cacheConfig.purgeKey}}</code-label> Header。只能包含字符、数字、下划线。</p>
|
<p class="comment"><a href="" @click.prevent="generatePurgeKey">[随机生成]</a>。需要在PURGE方法调用时加入<code-label>X-Edge-Purge-Key: {{cacheConfig.purgeKey}}</code-label> Header。只能包含字符、数字、下划线。</p>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
</tbody>
|
</tbody>
|
||||||
|
|||||||
@@ -26,7 +26,7 @@ Vue.component("http-charsets-box", {
|
|||||||
<prior-checkbox :v-config="charsetConfig" v-if="vIsLocation || vIsGroup"></prior-checkbox>
|
<prior-checkbox :v-config="charsetConfig" v-if="vIsLocation || vIsGroup"></prior-checkbox>
|
||||||
<tbody v-show="(!vIsLocation && !vIsGroup) || charsetConfig.isPrior">
|
<tbody v-show="(!vIsLocation && !vIsGroup) || charsetConfig.isPrior">
|
||||||
<tr>
|
<tr>
|
||||||
<td class="title">是否启用</td>
|
<td class="title">启用</td>
|
||||||
<td>
|
<td>
|
||||||
<div class="ui checkbox">
|
<div class="ui checkbox">
|
||||||
<input type="checkbox" v-model="charsetConfig.isOn"/>
|
<input type="checkbox" v-model="charsetConfig.isOn"/>
|
||||||
|
|||||||
@@ -148,7 +148,7 @@ Vue.component("http-compression-config-box", {
|
|||||||
<prior-checkbox :v-config="config" v-if="vIsLocation || vIsGroup"></prior-checkbox>
|
<prior-checkbox :v-config="config" v-if="vIsLocation || vIsGroup"></prior-checkbox>
|
||||||
<tbody v-show="(!vIsLocation && !vIsGroup) || config.isPrior">
|
<tbody v-show="(!vIsLocation && !vIsGroup) || config.isPrior">
|
||||||
<tr>
|
<tr>
|
||||||
<td class="title">是否启用</td>
|
<td class="title">启用</td>
|
||||||
<td>
|
<td>
|
||||||
<div class="ui checkbox">
|
<div class="ui checkbox">
|
||||||
<input type="checkbox" value="1" v-model="config.isOn"/>
|
<input type="checkbox" value="1" v-model="config.isOn"/>
|
||||||
|
|||||||
@@ -39,7 +39,7 @@ Vue.component("http-expires-time-config-box", {
|
|||||||
<prior-checkbox :v-config="expiresTime"></prior-checkbox>
|
<prior-checkbox :v-config="expiresTime"></prior-checkbox>
|
||||||
<tbody v-show="expiresTime.isPrior">
|
<tbody v-show="expiresTime.isPrior">
|
||||||
<tr>
|
<tr>
|
||||||
<td class="title">是否启用</td>
|
<td class="title">启用</td>
|
||||||
<td><checkbox v-model="expiresTime.isOn"></checkbox>
|
<td><checkbox v-model="expiresTime.isOn"></checkbox>
|
||||||
<p class="comment">启用后,将会在响应的Header中添加<code-label>Expires</code-label>字段,浏览器据此会将内容缓存在客户端;同时,在管理后台执行清理缓存时,也将无法清理客户端已有的缓存。</p>
|
<p class="comment">启用后,将会在响应的Header中添加<code-label>Expires</code-label>字段,浏览器据此会将内容缓存在客户端;同时,在管理后台执行清理缓存时,也将无法清理客户端已有的缓存。</p>
|
||||||
</td>
|
</td>
|
||||||
|
|||||||
@@ -61,7 +61,7 @@ Vue.component("http-fastcgi-box", {
|
|||||||
<prior-checkbox :v-config="fastcgiRef" v-if="vIsLocation"></prior-checkbox>
|
<prior-checkbox :v-config="fastcgiRef" v-if="vIsLocation"></prior-checkbox>
|
||||||
<tbody v-show="(!this.vIsLocation || this.fastcgiRef.isPrior)">
|
<tbody v-show="(!this.vIsLocation || this.fastcgiRef.isPrior)">
|
||||||
<tr>
|
<tr>
|
||||||
<td class="title">是否启用配置</td>
|
<td class="title">启用配置</td>
|
||||||
<td>
|
<td>
|
||||||
<div class="ui checkbox">
|
<div class="ui checkbox">
|
||||||
<input type="checkbox" v-model="fastcgiRef.isOn"/>
|
<input type="checkbox" v-model="fastcgiRef.isOn"/>
|
||||||
|
|||||||
@@ -114,7 +114,7 @@ Vue.component("http-pages-and-shutdown-box", {
|
|||||||
<prior-checkbox :v-config="shutdownConfig" v-if="vIsLocation"></prior-checkbox>
|
<prior-checkbox :v-config="shutdownConfig" v-if="vIsLocation"></prior-checkbox>
|
||||||
<tbody v-show="!vIsLocation || shutdownConfig.isPrior">
|
<tbody v-show="!vIsLocation || shutdownConfig.isPrior">
|
||||||
<tr>
|
<tr>
|
||||||
<td class="title">是否开启</td>
|
<td class="title">开启</td>
|
||||||
<td>
|
<td>
|
||||||
<div class="ui checkbox">
|
<div class="ui checkbox">
|
||||||
<input type="checkbox" value="1" v-model="shutdownConfig.isOn" />
|
<input type="checkbox" value="1" v-model="shutdownConfig.isOn" />
|
||||||
|
|||||||
@@ -80,7 +80,7 @@ Vue.component("http-websocket-box", {
|
|||||||
<prior-checkbox :v-config="websocketRef" v-if="vIsLocation || vIsGroup"></prior-checkbox>
|
<prior-checkbox :v-config="websocketRef" v-if="vIsLocation || vIsGroup"></prior-checkbox>
|
||||||
<tbody v-show="((!vIsLocation && !vIsGroup) || websocketRef.isPrior)">
|
<tbody v-show="((!vIsLocation && !vIsGroup) || websocketRef.isPrior)">
|
||||||
<tr>
|
<tr>
|
||||||
<td class="title">是否启用配置</td>
|
<td class="title">启用配置</td>
|
||||||
<td>
|
<td>
|
||||||
<div class="ui checkbox">
|
<div class="ui checkbox">
|
||||||
<input type="checkbox" v-model="websocketRef.isOn"/>
|
<input type="checkbox" v-model="websocketRef.isOn"/>
|
||||||
|
|||||||
@@ -158,7 +158,7 @@ Vue.component("reverse-proxy-box", {
|
|||||||
<prior-checkbox :v-config="reverseProxyRef" v-if="vIsLocation || vIsGroup"></prior-checkbox>
|
<prior-checkbox :v-config="reverseProxyRef" v-if="vIsLocation || vIsGroup"></prior-checkbox>
|
||||||
<tbody v-show="(!vIsLocation && !vIsGroup) || reverseProxyRef.isPrior">
|
<tbody v-show="(!vIsLocation && !vIsGroup) || reverseProxyRef.isPrior">
|
||||||
<tr>
|
<tr>
|
||||||
<td class="title">是否启用反向代理</td>
|
<td class="title">启用反向代理</td>
|
||||||
<td>
|
<td>
|
||||||
<div class="ui checkbox">
|
<div class="ui checkbox">
|
||||||
<input type="checkbox" v-model="reverseProxyRef.isOn"/>
|
<input type="checkbox" v-model="reverseProxyRef.isOn"/>
|
||||||
|
|||||||
@@ -55,7 +55,7 @@
|
|||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td>是否启用</td>
|
<td>启用节点</td>
|
||||||
<td>
|
<td>
|
||||||
<div class="ui checkbox">
|
<div class="ui checkbox">
|
||||||
<input type="checkbox" name="isOn" value="1" v-model="node.isOn"/>
|
<input type="checkbox" name="isOn" value="1" v-model="node.isOn"/>
|
||||||
|
|||||||
@@ -6,6 +6,6 @@
|
|||||||
<menu-item :href="'/servers/components/cache/stat?cachePolicyId=' + cachePolicyId" code="stat">统计</menu-item>
|
<menu-item :href="'/servers/components/cache/stat?cachePolicyId=' + cachePolicyId" code="stat">统计</menu-item>
|
||||||
<menu-item :href="'/servers/components/cache/clean?cachePolicyId=' + cachePolicyId" code="clean">清理</menu-item>
|
<menu-item :href="'/servers/components/cache/clean?cachePolicyId=' + cachePolicyId" code="clean">清理</menu-item>
|
||||||
<menu-item :href="'/servers/components/cache/purge?cachePolicyId=' + cachePolicyId" code="purge">删除</menu-item>
|
<menu-item :href="'/servers/components/cache/purge?cachePolicyId=' + cachePolicyId" code="purge">删除</menu-item>
|
||||||
<menu-item :href="'/servers/components/cache/preheat?cachePolicyId=' + cachePolicyId" code="preheat">预热</menu-item>
|
<menu-item :href="'/servers/components/cache/fetch?cachePolicyId=' + cachePolicyId" code="fetch">预热</menu-item>
|
||||||
<menu-item :href="'/servers/components/cache/update?cachePolicyId=' + cachePolicyId" code="update">修改</menu-item>
|
<menu-item :href="'/servers/components/cache/update?cachePolicyId=' + cachePolicyId" code="update">修改</menu-item>
|
||||||
</second-menu>
|
</second-menu>
|
||||||
|
|||||||
6
web/views/@default/servers/components/cache/batch/@menu.html
vendored
Normal file
6
web/views/@default/servers/components/cache/batch/@menu.html
vendored
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
<first-menu>
|
||||||
|
<menu-item href="." code="purge">刷新缓存</menu-item>
|
||||||
|
<menu-item href=".fetch" code="fetch">预热缓存</menu-item>
|
||||||
|
<span class="item disabled">|</span>
|
||||||
|
<menu-item href=".tasks" code="task">所有任务<span v-if="countDoingTasks > 0" class="grey">({{countDoingTasks}})</span></menu-item>
|
||||||
|
</first-menu>
|
||||||
28
web/views/@default/servers/components/cache/batch/fetch.html
vendored
Normal file
28
web/views/@default/servers/components/cache/batch/fetch.html
vendored
Normal file
@@ -0,0 +1,28 @@
|
|||||||
|
{$layout}
|
||||||
|
{$template "menu"}
|
||||||
|
|
||||||
|
<form method="post" class="ui form" data-tea-action="$" data-tea-before="before" data-tea-success="success" data-tea-fail="fail" data-tea-done="done" data-tea-timeout="3600">
|
||||||
|
<csrf-token></csrf-token>
|
||||||
|
<table class="ui table definition selectable">
|
||||||
|
<tr>
|
||||||
|
<td>要预热的Key列表</td>
|
||||||
|
<td>
|
||||||
|
<textarea name="keys" rows="10" ref="focus"></textarea>
|
||||||
|
<p class="comment">每行一个Key。</p>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td class="title">操作结果</td>
|
||||||
|
<td>
|
||||||
|
<div v-if="isRequesting">数据发送中...</div>
|
||||||
|
<span class="red" v-if="!isRequesting && !isOk && message.length > 0">失败:{{message}}</span>
|
||||||
|
<div v-if="!isRequesting && !isOk && failKeys.length > 0" class="fail-keys-box">
|
||||||
|
<div v-for="failKey in failKeys">
|
||||||
|
<span class="red">{{failKey.key}}: {{failKey.reason}}</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
|
<submit-btn v-if="!isRequesting">提交</submit-btn>
|
||||||
|
</form>
|
||||||
@@ -2,22 +2,28 @@ Tea.context(function () {
|
|||||||
this.isRequesting = false
|
this.isRequesting = false
|
||||||
this.isOk = false
|
this.isOk = false
|
||||||
this.message = ""
|
this.message = ""
|
||||||
this.results = []
|
this.failKeys = []
|
||||||
|
|
||||||
this.before = function () {
|
this.before = function () {
|
||||||
this.isRequesting = true
|
this.isRequesting = true
|
||||||
this.isOk = false
|
this.isOk = false
|
||||||
this.message = ""
|
this.message = ""
|
||||||
this.results = []
|
this.failKeys = []
|
||||||
}
|
}
|
||||||
|
|
||||||
this.success = function (resp) {
|
this.success = function (resp) {
|
||||||
this.isOk = true
|
this.isOk = true
|
||||||
this.results = resp.data.results
|
|
||||||
|
let f = NotifyReloadSuccess("任务提交成功")
|
||||||
|
f()
|
||||||
}
|
}
|
||||||
|
|
||||||
this.fail = function (resp) {
|
this.fail = function (resp) {
|
||||||
this.message = resp.message
|
this.message = resp.message
|
||||||
|
|
||||||
|
if (resp.data.failKeys != null) {
|
||||||
|
this.failKeys = resp.data.failKeys
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
this.done = function () {
|
this.done = function () {
|
||||||
8
web/views/@default/servers/components/cache/batch/index.css
vendored
Normal file
8
web/views/@default/servers/components/cache/batch/index.css
vendored
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
.fail-keys-box {
|
||||||
|
max-height: 10em;
|
||||||
|
overflow-y: auto;
|
||||||
|
}
|
||||||
|
.fail-keys-box::-webkit-scrollbar {
|
||||||
|
width: 6px;
|
||||||
|
}
|
||||||
|
/*# sourceMappingURL=index.css.map */
|
||||||
1
web/views/@default/servers/components/cache/batch/index.css.map
vendored
Normal file
1
web/views/@default/servers/components/cache/batch/index.css.map
vendored
Normal file
@@ -0,0 +1 @@
|
|||||||
|
{"version":3,"sources":["index.less"],"names":[],"mappings":"AAAA;EACC,gBAAA;EACA,gBAAA;;AAGD,cAAc;EACb,UAAA","file":"index.css"}
|
||||||
41
web/views/@default/servers/components/cache/batch/index.html
vendored
Normal file
41
web/views/@default/servers/components/cache/batch/index.html
vendored
Normal file
@@ -0,0 +1,41 @@
|
|||||||
|
{$layout}
|
||||||
|
{$template "menu"}
|
||||||
|
|
||||||
|
<div class="margin"></div>
|
||||||
|
|
||||||
|
<form method="post" class="ui form" data-tea-action="$" data-tea-before="before" data-tea-success="success" data-tea-fail="fail" data-tea-done="done" data-tea-timeout="300">
|
||||||
|
<csrf-token></csrf-token>
|
||||||
|
<table class="ui table definition selectable">
|
||||||
|
<tr>
|
||||||
|
<td class="title">缓存Key类型</td>
|
||||||
|
<td>
|
||||||
|
<radio name="keyType" :v-value="'key'" v-model="keyType">根据Key</radio>
|
||||||
|
<radio name="keyType" :v-value="'prefix'" v-model="keyType">根据前缀</radio>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>
|
||||||
|
<span v-if="keyType == 'key'">要刷新的Key列表</span>
|
||||||
|
<span v-if="keyType == 'prefix'">要刷新的Key前缀列表</span>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<textarea name="keys" rows="10" ref="keysBox"></textarea>
|
||||||
|
<p class="comment" v-if="keyType == 'key'">每行一个Key,比如是一个完整的URL<code-label>https://example.com/hello/world.html</code-label>。</p>
|
||||||
|
<p class="comment" v-if="keyType == 'prefix'">每行一个Key前缀,比如是一个URL前缀<code-label>https://example.com/hello/</code-label>。</p>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>操作结果</td>
|
||||||
|
<td>
|
||||||
|
<div v-if="isRequesting">数据发送中...</div>
|
||||||
|
<span class="red" v-if="!isRequesting && !isOk && message.length > 0">失败:{{message}}</span>
|
||||||
|
<div v-if="!isRequesting && !isOk && failKeys.length > 0" class="fail-keys-box">
|
||||||
|
<div v-for="failKey in failKeys">
|
||||||
|
<span class="red">{{failKey.key}}: {{failKey.reason}}</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
|
<submit-btn v-if="!isRequesting">提交</submit-btn>
|
||||||
|
</form>
|
||||||
43
web/views/@default/servers/components/cache/batch/index.js
vendored
Normal file
43
web/views/@default/servers/components/cache/batch/index.js
vendored
Normal file
@@ -0,0 +1,43 @@
|
|||||||
|
Tea.context(function () {
|
||||||
|
this.isRequesting = false
|
||||||
|
this.isOk = false
|
||||||
|
this.message = ""
|
||||||
|
this.failKeys = []
|
||||||
|
|
||||||
|
this.$delay(function () {
|
||||||
|
this.$refs.keysBox.focus()
|
||||||
|
this.$watch("keyType", function () {
|
||||||
|
this.$refs.keysBox.focus()
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
this.before = function () {
|
||||||
|
this.isRequesting = true
|
||||||
|
this.isOk = false
|
||||||
|
this.message = ""
|
||||||
|
this.failKeys = []
|
||||||
|
}
|
||||||
|
|
||||||
|
this.success = function () {
|
||||||
|
this.isOk = true
|
||||||
|
let f = NotifyReloadSuccess("任务提交成功")
|
||||||
|
f()
|
||||||
|
}
|
||||||
|
|
||||||
|
this.fail = function (resp) {
|
||||||
|
this.message = resp.message
|
||||||
|
|
||||||
|
if (resp.data.failKeys != null) {
|
||||||
|
this.failKeys = resp.data.failKeys
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
this.done = function () {
|
||||||
|
this.isRequesting = false
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 操作类型
|
||||||
|
*/
|
||||||
|
this.keyType = "key" // key | prefix
|
||||||
|
})
|
||||||
8
web/views/@default/servers/components/cache/batch/index.less
vendored
Normal file
8
web/views/@default/servers/components/cache/batch/index.less
vendored
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
.fail-keys-box {
|
||||||
|
max-height: 10em;
|
||||||
|
overflow-y: auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
.fail-keys-box::-webkit-scrollbar {
|
||||||
|
width: 6px;
|
||||||
|
}
|
||||||
94
web/views/@default/servers/components/cache/batch/task.html
vendored
Normal file
94
web/views/@default/servers/components/cache/batch/task.html
vendored
Normal file
@@ -0,0 +1,94 @@
|
|||||||
|
{$layout}
|
||||||
|
{$template "menu"}
|
||||||
|
|
||||||
|
<second-menu>
|
||||||
|
<menu-item href=".tasks">所有任务</menu-item>
|
||||||
|
<span class="disabled item" style="padding: 0">»</span>
|
||||||
|
<span class="item">任务详情</span>
|
||||||
|
</second-menu>
|
||||||
|
|
||||||
|
<table class="ui table definition selectable">
|
||||||
|
<tr>
|
||||||
|
<td class="title">任务编号</td>
|
||||||
|
<td>{{task.id}}</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>任务类型</td>
|
||||||
|
<td>
|
||||||
|
<span v-if="task.type == 'purge'">刷新</span>
|
||||||
|
<span v-if="task.type == 'fetch'">预热</span>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>Key类型</td>
|
||||||
|
<td>
|
||||||
|
<span v-if="task.keyType == 'key'">URL</span>
|
||||||
|
<span v-if="task.keyType == 'prefix'">前缀</span>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>创建时间</td>
|
||||||
|
<td>
|
||||||
|
{{task.createdTime}}
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>完成时间</td>
|
||||||
|
<td>
|
||||||
|
<span v-if="task.isDone">{{task.doneTime}}</span>
|
||||||
|
<span v-else class="disabled">尚未完成</span>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>所属用户</td>
|
||||||
|
<td>
|
||||||
|
<span v-if="task.user != null && task.user.id > 0"><user-link :v-user="task.user"></user-link></span>
|
||||||
|
<span v-else="" class="disabled">-</span>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>任务状态</td>
|
||||||
|
<td>
|
||||||
|
<span v-if="task.isOk" class="green">已完成</span>
|
||||||
|
<a :href="'/servers/components/cache/batch/task?taskId=' + task.id" v-else-if="task.isDone" class="red"><span class="red">失败</span></a>
|
||||||
|
<span v-else-if="!task.isDone" class="grey">等待执行</span>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>操作</td>
|
||||||
|
<td>
|
||||||
|
<a href="" @click.prevent="deleteTask(task.id)">[删除]</a>
|
||||||
|
<a href="" @click.prevent="resetTask(task.id)">[重置状态]</a>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
|
|
||||||
|
<h4>要操作的缓存Key</h4>
|
||||||
|
<table class="ui table selectable celled">
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th>
|
||||||
|
<span v-if="task.keyType == 'key'">URL</span>
|
||||||
|
<span v-if="task.keyType == 'prefix'">前缀</span>
|
||||||
|
</th>
|
||||||
|
<th class="width5">状态</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody v-for="key in task.keys">
|
||||||
|
<tr>
|
||||||
|
<td>{{key.key}}
|
||||||
|
|
||||||
|
<div v-if="key.errors.length > 0" style="margin-top: 0.5em">
|
||||||
|
<a :href="'/clusters/cluster/node?nodeId=' + err.nodeId" v-for="err in key.errors" class="ui label basic tiny red">
|
||||||
|
节点{{err.nodeId}}:{{err.error}}
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<span v-if="key.isDone && key.errors.length == 0" class="green">完成</span>
|
||||||
|
<span v-if="key.isDone && key.errors.length > 0" class="red">失败</span>
|
||||||
|
<span v-if="!key.isDone" class="grey">未执行</span>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
23
web/views/@default/servers/components/cache/batch/task.js
vendored
Normal file
23
web/views/@default/servers/components/cache/batch/task.js
vendored
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
Tea.context(function () {
|
||||||
|
this.deleteTask = function (taskId) {
|
||||||
|
teaweb.confirm("确定要删除此任务吗?", function () {
|
||||||
|
this.$post(".deleteTask")
|
||||||
|
.params({
|
||||||
|
taskId: taskId
|
||||||
|
})
|
||||||
|
.success(function () {
|
||||||
|
window.location = Tea.url(".tasks")
|
||||||
|
})
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
this.resetTask = function (taskId) {
|
||||||
|
teaweb.confirm("确定要重置任务状态吗?", function () {
|
||||||
|
this.$post(".resetTask")
|
||||||
|
.params({
|
||||||
|
taskId: taskId
|
||||||
|
})
|
||||||
|
.refresh()
|
||||||
|
})
|
||||||
|
}
|
||||||
|
})
|
||||||
48
web/views/@default/servers/components/cache/batch/tasks.html
vendored
Normal file
48
web/views/@default/servers/components/cache/batch/tasks.html
vendored
Normal file
@@ -0,0 +1,48 @@
|
|||||||
|
{$layout}
|
||||||
|
{$template "menu"}
|
||||||
|
|
||||||
|
<p class="comment" v-if="tasks.length == 0">暂时还没有任务。</p>
|
||||||
|
|
||||||
|
<table class="ui table selectable celled" v-if="tasks.length > 0">
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th style="width: 7em">任务编号</th>
|
||||||
|
<th>任务类型</th>
|
||||||
|
<th>Key类型</th>
|
||||||
|
<th>创建时间</th>
|
||||||
|
<th class="four wide">所属用户</th>
|
||||||
|
<th class="two wide">任务状态</th>
|
||||||
|
<th class="two op">操作</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody v-for="task in tasks">
|
||||||
|
<tr>
|
||||||
|
<td><a :href="'/servers/components/cache/batch/task?taskId=' + task.id">{{task.id}}</a></td>
|
||||||
|
<td>
|
||||||
|
<span v-if="task.type == 'purge'">刷新</span>
|
||||||
|
<span v-if="task.type == 'fetch'">预热</span>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<span v-if="task.keyType == 'key'">URL</span>
|
||||||
|
<span v-if="task.keyType == 'prefix'">前缀</span>
|
||||||
|
</td>
|
||||||
|
<td>{{task.createdTime}}</td>
|
||||||
|
<td>
|
||||||
|
<span v-if="task.user != null && task.user.id > 0"><user-link :v-user="task.user"></user-link></span>
|
||||||
|
<span v-if="task.description.length > 0" class="grey">{{task.description}}</span>
|
||||||
|
<span v-else="" class="disabled">-</span>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<span v-if="task.isOk" class="green">已完成</span>
|
||||||
|
<a :href="'/servers/components/cache/batch/task?taskId=' + task.id" v-else-if="task.isDone" class="red"><span class="red">失败</span></a>
|
||||||
|
<span v-else-if="!task.isDone" class="grey">等待执行</span>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<a :href="'/servers/components/cache/batch/task?taskId=' + task.id">详情</a>
|
||||||
|
<a href="" @click.prevent="deleteTask(task.id)">删除</a>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
|
||||||
|
<page-box></page-box>
|
||||||
11
web/views/@default/servers/components/cache/batch/tasks.js
vendored
Normal file
11
web/views/@default/servers/components/cache/batch/tasks.js
vendored
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
Tea.context(function () {
|
||||||
|
this.deleteTask = function (taskId) {
|
||||||
|
teaweb.confirm("确定要删除此任务吗?", function () {
|
||||||
|
this.$post(".deleteTask")
|
||||||
|
.params({
|
||||||
|
taskId: taskId
|
||||||
|
})
|
||||||
|
.refresh()
|
||||||
|
})
|
||||||
|
}
|
||||||
|
})
|
||||||
@@ -1,15 +1,8 @@
|
|||||||
{$layout}
|
{$layout}
|
||||||
{$template "policy_menu"}
|
{$template "policy_menu"}
|
||||||
|
|
||||||
<h3>选择集群</h3>
|
|
||||||
<select class="ui dropdown auto-width" v-model="clusterId">
|
|
||||||
<option v-for="cluster in clusters" :value="cluster.id">{{cluster.name}}</option>
|
|
||||||
</select>
|
|
||||||
<div class="ui divider"></div>
|
|
||||||
|
|
||||||
<form method="post" class="ui form" data-tea-action="$" data-tea-before="before" data-tea-success="success" data-tea-fail="fail" data-tea-done="done" data-tea-timeout="3600">
|
<form method="post" class="ui form" data-tea-action="$" data-tea-before="before" data-tea-success="success" data-tea-fail="fail" data-tea-done="done" data-tea-timeout="3600">
|
||||||
<input type="hidden" name="cachePolicyId" :value="cachePolicyId"/>
|
<input type="hidden" name="cachePolicyId" :value="cachePolicyId"/>
|
||||||
<input type="hidden" name="clusterId" :value="clusterId"/>
|
|
||||||
<table class="ui table definition selectable">
|
<table class="ui table definition selectable">
|
||||||
<tr>
|
<tr>
|
||||||
<td>Key列表</td>
|
<td>Key列表</td>
|
||||||
@@ -23,9 +16,10 @@
|
|||||||
<td>
|
<td>
|
||||||
<div v-if="isRequesting">数据发送中...</div>
|
<div v-if="isRequesting">数据发送中...</div>
|
||||||
<span class="red" v-if="!isRequesting && !isOk && message.length > 0">失败:{{message}}</span>
|
<span class="red" v-if="!isRequesting && !isOk && message.length > 0">失败:{{message}}</span>
|
||||||
<div v-if="!isRequesting && isOk">
|
<div v-if="!isRequesting && !isOk && failKeys.length > 0" class="fail-keys-box">
|
||||||
<span v-if="results.length == 0" class="red">此集群下没有任何可用的节点。</span>
|
<div v-for="failKey in failKeys">
|
||||||
<div class="ui label tiny" v-for="one in results" :class="{green:one.isOk, red:!one.isOk}" style="margin-bottom: 0.5em">{{one.nodeName}}:{{one.message}}</div>
|
<span class="red">{{failKey.key}}: {{failKey.reason}}</span>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
@@ -2,22 +2,28 @@ Tea.context(function () {
|
|||||||
this.isRequesting = false
|
this.isRequesting = false
|
||||||
this.isOk = false
|
this.isOk = false
|
||||||
this.message = ""
|
this.message = ""
|
||||||
this.results = []
|
this.failKeys = []
|
||||||
|
|
||||||
this.before = function () {
|
this.before = function () {
|
||||||
this.isRequesting = true
|
this.isRequesting = true
|
||||||
this.isOk = false
|
this.isOk = false
|
||||||
this.message = ""
|
this.message = ""
|
||||||
this.results = []
|
this.failKeys = []
|
||||||
}
|
}
|
||||||
|
|
||||||
this.success = function (resp) {
|
this.success = function (resp) {
|
||||||
this.isOk = true
|
this.isOk = true
|
||||||
this.results = resp.data.results
|
|
||||||
|
let f = NotifyReloadSuccess("任务提交成功")
|
||||||
|
f()
|
||||||
}
|
}
|
||||||
|
|
||||||
this.fail = function (resp) {
|
this.fail = function (resp) {
|
||||||
this.message = resp.message
|
this.message = resp.message
|
||||||
|
|
||||||
|
if (resp.data.failKeys != null) {
|
||||||
|
this.failKeys = resp.data.failKeys
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
this.done = function () {
|
this.done = function () {
|
||||||
@@ -1,34 +1,26 @@
|
|||||||
{$layout}
|
{$layout}
|
||||||
{$template "policy_menu"}
|
{$template "policy_menu"}
|
||||||
|
|
||||||
<h3>选择集群</h3>
|
|
||||||
<select class="ui dropdown auto-width" v-model="clusterId">
|
|
||||||
<option v-for="cluster in clusters" :value="cluster.id">{{cluster.name}}</option>
|
|
||||||
</select>
|
|
||||||
<div class="ui divider"></div>
|
|
||||||
|
|
||||||
<h3>批量删除</h3>
|
|
||||||
<p class="comment">可以在这里批量删除一组Key。</p>
|
<p class="comment">可以在这里批量删除一组Key。</p>
|
||||||
<form method="post" class="ui form" data-tea-action="$" data-tea-before="before" data-tea-success="success" data-tea-fail="fail" data-tea-done="done" data-tea-timeout="300">
|
<form method="post" class="ui form" data-tea-action="$" data-tea-before="before" data-tea-success="success" data-tea-fail="fail" data-tea-done="done" data-tea-timeout="300">
|
||||||
<input type="hidden" name="cachePolicyId" :value="cachePolicyId"/>
|
<input type="hidden" name="cachePolicyId" :value="cachePolicyId"/>
|
||||||
<input type="hidden" name="clusterId" :value="clusterId"/>
|
|
||||||
<table class="ui table definition selectable">
|
<table class="ui table definition selectable">
|
||||||
<tr>
|
<tr>
|
||||||
<td class="title">操作类型</td>
|
<td class="title">操作类型</td>
|
||||||
<td>
|
<td>
|
||||||
<radio name="type" :v-value="'key'" v-model="type">根据Key</radio>
|
<radio name="keyType" :v-value="'key'" v-model="keyType">根据Key</radio>
|
||||||
<radio name="type" :v-value="'prefix'" v-model="type">根据前缀</radio>
|
<radio name="keyType" :v-value="'prefix'" v-model="keyType">根据前缀</radio>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td>
|
<td>
|
||||||
<span v-if="type == 'key'">Key列表</span>
|
<span v-if="keyType == 'key'">Key列表</span>
|
||||||
<span v-if="type == 'prefix'">Key前缀列表</span>
|
<span v-if="keyType == 'prefix'">Key前缀列表</span>
|
||||||
</td>
|
</td>
|
||||||
<td>
|
<td>
|
||||||
<textarea name="keys" rows="10" ref="focus"></textarea>
|
<textarea name="keys" rows="10" ref="keysBox"></textarea>
|
||||||
<p class="comment" v-if="type == 'key'">每行一个Key,比如是一个完整的URL<code-label>https://example.com/hello/world.html</code-label>。</p>
|
<p class="comment" v-if="keyType == 'key'">每行一个Key,比如是一个完整的URL<code-label>https://example.com/hello/world.html</code-label>。</p>
|
||||||
<p class="comment" v-if="type == 'prefix'">每行一个Key前缀,比如是一个URL前缀<code-label>https://example.com/hello/</code-label>。</p>
|
<p class="comment" v-if="keyType == 'prefix'">每行一个Key前缀,比如是一个URL前缀<code-label>https://example.com/hello/</code-label>。</p>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
@@ -36,9 +28,10 @@
|
|||||||
<td>
|
<td>
|
||||||
<div v-if="isRequesting">数据发送中...</div>
|
<div v-if="isRequesting">数据发送中...</div>
|
||||||
<span class="red" v-if="!isRequesting && !isOk && message.length > 0">失败:{{message}}</span>
|
<span class="red" v-if="!isRequesting && !isOk && message.length > 0">失败:{{message}}</span>
|
||||||
<div v-if="!isRequesting && isOk">
|
<div v-if="!isRequesting && !isOk && failKeys.length > 0" class="fail-keys-box">
|
||||||
<span v-if="results.length == 0" class="red">此集群下没有任何可用的节点。</span>
|
<div v-for="failKey in failKeys">
|
||||||
<div class="ui label tiny" v-for="one in results" :class="{green:one.isOk, red:!one.isOk}" style="margin-bottom: 0.5em">{{one.nodeName}}:{{one.message}}</div>
|
<span class="red">{{failKey.key}}: {{failKey.reason}}</span>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
|
|||||||
@@ -1,31 +1,35 @@
|
|||||||
Tea.context(function () {
|
Tea.context(function () {
|
||||||
if (this.clusterId == null) {
|
|
||||||
if (this.clusters.length > 0) {
|
|
||||||
this.clusterId = this.clusters[0].id
|
|
||||||
} else {
|
|
||||||
this.clusterId = 0
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
this.isRequesting = false
|
this.isRequesting = false
|
||||||
this.isOk = false
|
this.isOk = false
|
||||||
this.message = ""
|
this.message = ""
|
||||||
this.results = []
|
this.failKeys = []
|
||||||
|
|
||||||
|
this.$delay(function () {
|
||||||
|
this.$refs.keysBox.focus()
|
||||||
|
this.$watch("keyType", function () {
|
||||||
|
this.$refs.keysBox.focus()
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
this.before = function () {
|
this.before = function () {
|
||||||
this.isRequesting = true
|
this.isRequesting = true
|
||||||
this.isOk = false
|
this.isOk = false
|
||||||
this.message = ""
|
this.message = ""
|
||||||
this.results = []
|
this.failKeys = []
|
||||||
}
|
}
|
||||||
|
|
||||||
this.success = function (resp) {
|
this.success = function () {
|
||||||
this.isOk = true
|
this.isOk = true
|
||||||
this.results = resp.data.results
|
let f = NotifyReloadSuccess("任务提交成功")
|
||||||
|
f()
|
||||||
}
|
}
|
||||||
|
|
||||||
this.fail = function (resp) {
|
this.fail = function (resp) {
|
||||||
this.message = resp.message
|
this.message = resp.message
|
||||||
|
|
||||||
|
if (resp.data.failKeys != null) {
|
||||||
|
this.failKeys = resp.data.failKeys
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
this.done = function () {
|
this.done = function () {
|
||||||
@@ -35,5 +39,5 @@ Tea.context(function () {
|
|||||||
/**
|
/**
|
||||||
* 操作类型
|
* 操作类型
|
||||||
*/
|
*/
|
||||||
this.type = "key" // key | prefix
|
this.keyType = "key" // key | prefix
|
||||||
})
|
})
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
<first-menu>
|
<first-menu>
|
||||||
<menu-item :href="'.?serverId=' + serverId" code="index">设置</menu-item>
|
<menu-item :href="'.?serverId=' + serverId" code="index">设置</menu-item>
|
||||||
<menu-item :href="'.purge?serverId=' + serverId" code="purge">清理</menu-item>
|
<menu-item :href="'.purge?serverId=' + serverId" code="purge">清理</menu-item>
|
||||||
<menu-item :href="'.preheat?serverId=' + serverId" code="preheat">预热</menu-item>
|
<menu-item :href="'.fetch?serverId=' + serverId" code="fetch">预热</menu-item>
|
||||||
</first-menu>
|
</first-menu>
|
||||||
@@ -26,9 +26,10 @@
|
|||||||
<td>
|
<td>
|
||||||
<div v-if="isRequesting">数据发送中...</div>
|
<div v-if="isRequesting">数据发送中...</div>
|
||||||
<span class="red" v-if="!isRequesting && !isOk && message.length > 0">失败:{{message}}</span>
|
<span class="red" v-if="!isRequesting && !isOk && message.length > 0">失败:{{message}}</span>
|
||||||
<div v-if="!isRequesting && isOk">
|
<div v-if="!isRequesting && !isOk && failKeys.length > 0" class="fail-keys-box">
|
||||||
<span v-if="results.length == 0" class="red">此集群下没有任何可用的节点。</span>
|
<div v-for="failKey in failKeys">
|
||||||
<div class="ui label tiny" v-for="one in results" :class="{green:one.isOk, red:!one.isOk}" style="margin-bottom: 0.5em">{{one.nodeName}}:{{one.message}}</div>
|
<span class="red">{{failKey.key}}: {{failKey.reason}}</span>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
@@ -1,31 +1,29 @@
|
|||||||
Tea.context(function () {
|
Tea.context(function () {
|
||||||
if (this.clusterId == null) {
|
|
||||||
if (this.clusters.length > 0) {
|
|
||||||
this.clusterId = this.clusters[0].id
|
|
||||||
} else {
|
|
||||||
this.clusterId = 0
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
this.isRequesting = false
|
this.isRequesting = false
|
||||||
this.isOk = false
|
this.isOk = false
|
||||||
this.message = ""
|
this.message = ""
|
||||||
this.results = []
|
this.failKeys = []
|
||||||
|
|
||||||
this.before = function () {
|
this.before = function () {
|
||||||
this.isRequesting = true
|
this.isRequesting = true
|
||||||
this.isOk = false
|
this.isOk = false
|
||||||
this.message = ""
|
this.message = ""
|
||||||
this.results = []
|
this.failKeys = []
|
||||||
}
|
}
|
||||||
|
|
||||||
this.success = function (resp) {
|
this.success = function (resp) {
|
||||||
this.isOk = true
|
this.isOk = true
|
||||||
this.results = resp.data.results
|
|
||||||
|
let f = NotifyReloadSuccess("任务提交成功")
|
||||||
|
f()
|
||||||
}
|
}
|
||||||
|
|
||||||
this.fail = function (resp) {
|
this.fail = function (resp) {
|
||||||
this.message = resp.message
|
this.message = resp.message
|
||||||
|
|
||||||
|
if (resp.data.failKeys != null) {
|
||||||
|
this.failKeys = resp.data.failKeys
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
this.done = function () {
|
this.done = function () {
|
||||||
@@ -18,19 +18,19 @@
|
|||||||
<tr>
|
<tr>
|
||||||
<td class="title">操作类型</td>
|
<td class="title">操作类型</td>
|
||||||
<td>
|
<td>
|
||||||
<radio name="type" :v-value="'key'" v-model="type">根据Key</radio>
|
<radio name="keyType" :v-value="'key'" v-model="keyType">根据Key</radio>
|
||||||
<radio name="type" :v-value="'prefix'" v-model="type">根据前缀</radio>
|
<radio name="keyType" :v-value="'prefix'" v-model="keyType">根据前缀</radio>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td>
|
<td>
|
||||||
<span v-if="type == 'key'">Key列表</span>
|
<span v-if="keyType == 'key'">Key列表</span>
|
||||||
<span v-if="type == 'prefix'">Key前缀列表</span>
|
<span v-if="keyType == 'prefix'">Key前缀列表</span>
|
||||||
</td>
|
</td>
|
||||||
<td>
|
<td>
|
||||||
<textarea name="keys" rows="10" ref="focus"></textarea>
|
<textarea name="keys" rows="10" ref="keysBox"></textarea>
|
||||||
<p class="comment" v-if="type == 'key'">每行一个Key,比如是一个完整的URL<code-label>https://example.com/hello/world.html</code-label>。</p>
|
<p class="comment" v-if="keyType == 'key'">每行一个Key,比如是一个完整的URL<code-label>https://example.com/hello/world.html</code-label>。</p>
|
||||||
<p class="comment" v-if="type == 'prefix'">每行一个Key前缀,比如是一个URL前缀<code-label>https://example.com/hello/</code-label>。</p>
|
<p class="comment" v-if="keyType == 'prefix'">每行一个Key前缀,比如是一个URL前缀<code-label>https://example.com/hello/</code-label>。</p>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
@@ -38,9 +38,10 @@
|
|||||||
<td>
|
<td>
|
||||||
<div v-if="isRequesting">数据发送中...</div>
|
<div v-if="isRequesting">数据发送中...</div>
|
||||||
<span class="red" v-if="!isRequesting && !isOk && message.length > 0">失败:{{message}}</span>
|
<span class="red" v-if="!isRequesting && !isOk && message.length > 0">失败:{{message}}</span>
|
||||||
<div v-if="!isRequesting && isOk">
|
<div v-if="!isRequesting && !isOk && failKeys.length > 0" class="fail-keys-box">
|
||||||
<span v-if="results.length == 0" class="red">此集群下没有任何可用的节点。</span>
|
<div v-for="failKey in failKeys">
|
||||||
<div class="ui label tiny" v-for="one in results" :class="{green:one.isOk, red:!one.isOk}" style="margin-bottom: 0.5em">{{one.nodeName}}:{{one.message}}</div>
|
<span class="red">{{failKey.key}}: {{failKey.reason}}</span>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
|
|||||||
@@ -2,22 +2,34 @@ Tea.context(function () {
|
|||||||
this.isRequesting = false
|
this.isRequesting = false
|
||||||
this.isOk = false
|
this.isOk = false
|
||||||
this.message = ""
|
this.message = ""
|
||||||
this.results = []
|
this.failKeys = []
|
||||||
|
|
||||||
|
this.$delay(function () {
|
||||||
|
this.$refs.keysBox.focus()
|
||||||
|
this.$watch("keyType", function () {
|
||||||
|
this.$refs.keysBox.focus()
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
this.before = function () {
|
this.before = function () {
|
||||||
this.isRequesting = true
|
this.isRequesting = true
|
||||||
this.isOk = false
|
this.isOk = false
|
||||||
this.message = ""
|
this.message = ""
|
||||||
this.results = []
|
this.failKeys = []
|
||||||
}
|
}
|
||||||
|
|
||||||
this.success = function (resp) {
|
this.success = function () {
|
||||||
this.isOk = true
|
this.isOk = true
|
||||||
this.results = resp.data.results
|
let f = NotifyReloadSuccess("任务提交成功")
|
||||||
|
f()
|
||||||
}
|
}
|
||||||
|
|
||||||
this.fail = function (resp) {
|
this.fail = function (resp) {
|
||||||
this.message = resp.message
|
this.message = resp.message
|
||||||
|
|
||||||
|
if (resp.data.failKeys != null) {
|
||||||
|
this.failKeys = resp.data.failKeys
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
this.done = function () {
|
this.done = function () {
|
||||||
@@ -27,5 +39,5 @@ Tea.context(function () {
|
|||||||
/**
|
/**
|
||||||
* 操作类型
|
* 操作类型
|
||||||
*/
|
*/
|
||||||
this.type = "key" // key | prefix
|
this.keyType = "key" // key | prefix
|
||||||
})
|
})
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
<first-menu>
|
<first-menu>
|
||||||
<menu-item :href="'.?serverId=' + serverId" code="index">设置</menu-item>
|
<menu-item :href="'.?serverId=' + serverId" code="index">设置</menu-item>
|
||||||
<menu-item :href="'.purge?serverId=' + serverId" code="purge">清理</menu-item>
|
<menu-item :href="'.purge?serverId=' + serverId" code="purge">清理</menu-item>
|
||||||
<menu-item :href="'.preheat?serverId=' + serverId" code="preheat">预热</menu-item>
|
<menu-item :href="'.fetch?serverId=' + serverId" code="fetch">预热</menu-item>
|
||||||
</first-menu>
|
</first-menu>
|
||||||
@@ -7,7 +7,7 @@
|
|||||||
|
|
||||||
<div class="margin"></div>
|
<div class="margin"></div>
|
||||||
<div v-show="webConfig.cache == null || !webConfig.cache.isOn">
|
<div v-show="webConfig.cache == null || !webConfig.cache.isOn">
|
||||||
<p class="comment">没有开启缓存,不需要清理。</p>
|
<p class="comment">没有开启缓存,暂时无法预热缓存。</p>
|
||||||
</div>
|
</div>
|
||||||
<div v-show="webConfig.cache != null && webConfig.cache.isOn">
|
<div v-show="webConfig.cache != null && webConfig.cache.isOn">
|
||||||
<p class="comment">可以在这里批量预热一组Key。</p>
|
<p class="comment">可以在这里批量预热一组Key。</p>
|
||||||
@@ -27,9 +27,10 @@
|
|||||||
<td>
|
<td>
|
||||||
<div v-if="isRequesting">数据发送中...</div>
|
<div v-if="isRequesting">数据发送中...</div>
|
||||||
<span class="red" v-if="!isRequesting && !isOk && message.length > 0">失败:{{message}}</span>
|
<span class="red" v-if="!isRequesting && !isOk && message.length > 0">失败:{{message}}</span>
|
||||||
<div v-if="!isRequesting && isOk">
|
<div v-if="!isRequesting && !isOk && failKeys.length > 0" class="fail-keys-box">
|
||||||
<span v-if="results.length == 0" class="red">此集群下没有任何可用的节点。</span>
|
<div v-for="failKey in failKeys">
|
||||||
<div class="ui label tiny" v-for="one in results" :class="{green:one.isOk, red:!one.isOk}" style="margin-bottom: 0.5em">{{one.nodeName}}:{{one.message}}</div>
|
<span class="red">{{failKey.key}}: {{failKey.reason}}</span>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
32
web/views/@default/servers/server/settings/cache/fetch.js
vendored
Normal file
32
web/views/@default/servers/server/settings/cache/fetch.js
vendored
Normal file
@@ -0,0 +1,32 @@
|
|||||||
|
Tea.context(function () {
|
||||||
|
this.isRequesting = false
|
||||||
|
this.isOk = false
|
||||||
|
this.message = ""
|
||||||
|
this.failKeys = []
|
||||||
|
|
||||||
|
this.before = function () {
|
||||||
|
this.isRequesting = true
|
||||||
|
this.isOk = false
|
||||||
|
this.message = ""
|
||||||
|
this.failKeys = []
|
||||||
|
}
|
||||||
|
|
||||||
|
this.success = function (resp) {
|
||||||
|
this.isOk = true
|
||||||
|
|
||||||
|
let f = NotifyReloadSuccess("任务提交成功")
|
||||||
|
f()
|
||||||
|
}
|
||||||
|
|
||||||
|
this.fail = function (resp) {
|
||||||
|
this.message = resp.message
|
||||||
|
|
||||||
|
if (resp.data.failKeys != null) {
|
||||||
|
this.failKeys = resp.data.failKeys
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
this.done = function () {
|
||||||
|
this.isRequesting = false
|
||||||
|
}
|
||||||
|
});
|
||||||
@@ -19,19 +19,19 @@
|
|||||||
<tr>
|
<tr>
|
||||||
<td class="title">操作类型</td>
|
<td class="title">操作类型</td>
|
||||||
<td>
|
<td>
|
||||||
<radio name="type" :v-value="'key'" v-model="type">根据Key</radio>
|
<radio name="keyType" :v-value="'key'" v-model="keyType">根据Key</radio>
|
||||||
<radio name="type" :v-value="'prefix'" v-model="type">根据前缀</radio>
|
<radio name="keyType" :v-value="'prefix'" v-model="keyType">根据前缀</radio>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td>
|
<td>
|
||||||
<span v-if="type == 'key'">Key列表</span>
|
<span v-if="keyType == 'key'">Key列表</span>
|
||||||
<span v-if="type == 'prefix'">Key前缀列表</span>
|
<span v-if="keyType == 'prefix'">Key前缀列表</span>
|
||||||
</td>
|
</td>
|
||||||
<td>
|
<td>
|
||||||
<textarea name="keys" rows="10" ref="focus"></textarea>
|
<textarea name="keys" rows="10" ref="keysBox"></textarea>
|
||||||
<p class="comment" v-if="type == 'key'">每行一个Key,比如是一个完整的URL<code-label>https://example.com/hello/world.html</code-label>。</p>
|
<p class="comment" v-if="keyType == 'key'">每行一个Key,比如是一个完整的URL<code-label>https://example.com/hello/world.html</code-label>。</p>
|
||||||
<p class="comment" v-if="type == 'prefix'">每行一个Key前缀,比如是一个URL前缀<code-label>https://example.com/hello/</code-label>。</p>
|
<p class="comment" v-if="keyType == 'prefix'">每行一个Key前缀,比如是一个URL前缀<code-label>https://example.com/hello/</code-label>。</p>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
@@ -39,9 +39,10 @@
|
|||||||
<td>
|
<td>
|
||||||
<div v-if="isRequesting">数据发送中...</div>
|
<div v-if="isRequesting">数据发送中...</div>
|
||||||
<span class="red" v-if="!isRequesting && !isOk && message.length > 0">失败:{{message}}</span>
|
<span class="red" v-if="!isRequesting && !isOk && message.length > 0">失败:{{message}}</span>
|
||||||
<div v-if="!isRequesting && isOk">
|
<div v-if="!isRequesting && !isOk && failKeys.length > 0" class="fail-keys-box">
|
||||||
<span v-if="results.length == 0" class="red">此集群下没有任何可用的节点。</span>
|
<div v-for="failKey in failKeys">
|
||||||
<div class="ui label tiny" v-for="one in results" :class="{green:one.isOk, red:!one.isOk}" style="margin-bottom: 0.5em">{{one.nodeName}}:{{one.message}}</div>
|
<span class="red">{{failKey.key}}: {{failKey.reason}}</span>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
|
|||||||
@@ -2,22 +2,34 @@ Tea.context(function () {
|
|||||||
this.isRequesting = false
|
this.isRequesting = false
|
||||||
this.isOk = false
|
this.isOk = false
|
||||||
this.message = ""
|
this.message = ""
|
||||||
this.results = []
|
this.failKeys = []
|
||||||
|
|
||||||
|
this.$delay(function () {
|
||||||
|
this.$refs.keysBox.focus()
|
||||||
|
this.$watch("keyType", function () {
|
||||||
|
this.$refs.keysBox.focus()
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
this.before = function () {
|
this.before = function () {
|
||||||
this.isRequesting = true
|
this.isRequesting = true
|
||||||
this.isOk = false
|
this.isOk = false
|
||||||
this.message = ""
|
this.message = ""
|
||||||
this.results = []
|
this.failKeys = []
|
||||||
}
|
}
|
||||||
|
|
||||||
this.success = function (resp) {
|
this.success = function () {
|
||||||
this.isOk = true
|
this.isOk = true
|
||||||
this.results = resp.data.results
|
let f = NotifyReloadSuccess("任务提交成功")
|
||||||
|
f()
|
||||||
}
|
}
|
||||||
|
|
||||||
this.fail = function (resp) {
|
this.fail = function (resp) {
|
||||||
this.message = resp.message
|
this.message = resp.message
|
||||||
|
|
||||||
|
if (resp.data.failKeys != null) {
|
||||||
|
this.failKeys = resp.data.failKeys
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
this.done = function () {
|
this.done = function () {
|
||||||
@@ -27,5 +39,5 @@ Tea.context(function () {
|
|||||||
/**
|
/**
|
||||||
* 操作类型
|
* 操作类型
|
||||||
*/
|
*/
|
||||||
this.type = "key" // key | prefix
|
this.keyType = "key" // key | prefix
|
||||||
})
|
})
|
||||||
@@ -56,7 +56,7 @@
|
|||||||
<td class="title">已绑定的域名</td>
|
<td class="title">已绑定的域名</td>
|
||||||
<td>
|
<td>
|
||||||
<server-name-box :v-server-names="serverNames"></server-name-box>
|
<server-name-box :v-server-names="serverNames"></server-name-box>
|
||||||
<p class="comment">终端用户可以通过这些域名访问当前网站服务。</p>
|
<p class="comment">用户可以通过这些域名访问当前网站服务。</p>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
</table>
|
</table>
|
||||||
|
|||||||
Reference in New Issue
Block a user