From 7b0e98bf02cec78ac413a9ef641ebf26514f580f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=80=97=E5=AD=90?= Date: Thu, 17 Oct 2024 04:44:58 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E9=98=B2=E7=81=AB=E5=A2=99=E5=AE=8C?= =?UTF-8?q?=E5=96=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- internal/http/middleware/status.go | 3 +- internal/http/request/firewall.go | 12 +- internal/service/base.go | 2 +- internal/service/dashboard.go | 2 +- internal/service/firewall.go | 25 +- pkg/firewall/consts.go | 2 +- pkg/firewall/firewall.go | 101 +++++--- pkg/shell/exec.go | 32 --- pkg/types/system.go | 3 +- web/src/api/panel/safe/index.ts | 10 +- web/src/i18n/zh_CN.json | 58 ----- web/src/views/app/IndexView.vue | 2 +- web/src/views/apps/fail2ban/IndexView.vue | 20 +- web/src/views/apps/frp/IndexView.vue | 32 +-- web/src/views/apps/gitea/IndexView.vue | 12 +- web/src/views/apps/mysql/IndexView.vue | 22 +- web/src/views/apps/nginx/IndexView.vue | 16 +- web/src/views/apps/php/IndexView.vue | 24 +- web/src/views/apps/phpmyadmin/IndexView.vue | 4 +- web/src/views/apps/podman/IndexView.vue | 18 +- web/src/views/apps/postgresql/IndexView.vue | 22 +- web/src/views/apps/pureftpd/IndexView.vue | 18 +- web/src/views/apps/redis/IndexView.vue | 16 +- web/src/views/apps/rsync/IndexView.vue | 18 +- web/src/views/apps/s3fs/IndexView.vue | 2 +- web/src/views/apps/supervisor/IndexView.vue | 22 +- web/src/views/apps/toolbox/IndexView.vue | 10 +- web/src/views/backup/IndexView.vue | 2 +- web/src/views/file/UploadModal.vue | 2 +- web/src/views/home/IndexView.vue | 8 +- web/src/views/home/UpdateView.vue | 6 +- web/src/views/monitor/IndexView.vue | 2 +- web/src/views/safe/CreateModal.vue | 149 +++++++++++ web/src/views/safe/IndexView.vue | 263 ++++++++++++-------- web/src/views/safe/route.ts | 2 +- web/src/views/safe/types.ts | 7 +- web/src/views/website/EditView.vue | 4 +- 37 files changed, 490 insertions(+), 463 deletions(-) create mode 100644 web/src/views/safe/CreateModal.vue diff --git a/internal/http/middleware/status.go b/internal/http/middleware/status.go index f366f5a8..7cf22bba 100644 --- a/internal/http/middleware/status.go +++ b/internal/http/middleware/status.go @@ -3,8 +3,9 @@ package middleware import ( "net/http" - "github.com/TheTNB/panel/internal/app" "github.com/go-rat/chix" + + "github.com/TheTNB/panel/internal/app" ) // Status 检查程序状态 diff --git a/internal/http/request/firewall.go b/internal/http/request/firewall.go index 9401ddf5..a183179e 100644 --- a/internal/http/request/firewall.go +++ b/internal/http/request/firewall.go @@ -5,9 +5,11 @@ type FirewallStatus struct { } type FirewallRule struct { - PortStart uint `json:"port_start" validate:"required,gte=1,lte=65535"` - PortEnd uint `json:"port_end" validate:"required,gte=1,lte=65535"` - Protocols []string `json:"protocols" validate:"min=1,dive,oneof=tcp udp"` - Address string `json:"address"` - Strategy string `json:"strategy" validate:"required,oneof=accept drop"` + Family string `json:"family" validate:"required,oneof=ipv4 ipv6"` + PortStart uint `json:"port_start" validate:"required,gte=1,lte=65535"` + PortEnd uint `json:"port_end" validate:"required,gte=1,lte=65535"` + Protocol string `json:"protocol" validate:"min=1,oneof=tcp udp tcp/udp"` + Address string `json:"address"` + Strategy string `json:"strategy" validate:"required,oneof=accept drop reject"` + Direction string `json:"direction"` } diff --git a/internal/service/base.go b/internal/service/base.go index 702ed5cb..124cb63d 100644 --- a/internal/service/base.go +++ b/internal/service/base.go @@ -68,7 +68,7 @@ func Bind[T any](r *http.Request) (*T, error) { if err := binder.Query(req); err != nil { return nil, err } - if slices.Contains([]string{"POST", "PUT", "PATCH"}, strings.ToUpper(r.Method)) { + if slices.Contains([]string{"POST", "PUT", "PATCH", "DELETE"}, strings.ToUpper(r.Method)) { if err := binder.Body(req); err != nil { return nil, err } diff --git a/internal/service/dashboard.go b/internal/service/dashboard.go index 2b5a0f66..29aa1b16 100644 --- a/internal/service/dashboard.go +++ b/internal/service/dashboard.go @@ -2,7 +2,6 @@ package service import ( "fmt" - "github.com/shirou/gopsutil/disk" "net" "net/http" "regexp" @@ -10,6 +9,7 @@ import ( "github.com/go-rat/chix" "github.com/hashicorp/go-version" + "github.com/shirou/gopsutil/disk" "github.com/shirou/gopsutil/host" "github.com/spf13/cast" diff --git a/internal/service/firewall.go b/internal/service/firewall.go index bc82aaa0..3afbc445 100644 --- a/internal/service/firewall.go +++ b/internal/service/firewall.go @@ -2,7 +2,6 @@ package service import ( "net/http" - "slices" "github.com/go-rat/chix" @@ -80,13 +79,11 @@ func (s *FirewallService) CreateRule(w http.ResponseWriter, r *http.Request) { return } - for protocol := range slices.Values(req.Protocols) { - if err = s.firewall.Port(firewall.FireInfo{ - PortStart: req.PortStart, PortEnd: req.PortEnd, Protocol: protocol, Address: req.Address, Strategy: req.Strategy, - }, firewall.OperationAdd); err != nil { - Error(w, http.StatusInternalServerError, "%v", err) - return - } + if err = s.firewall.Port(firewall.FireInfo{ + Family: req.Family, PortStart: req.PortStart, PortEnd: req.PortEnd, Protocol: req.Protocol, Address: req.Address, Strategy: req.Strategy, Direction: req.Direction, + }, firewall.OperationAdd); err != nil { + Error(w, http.StatusInternalServerError, "%v", err) + return } Success(w, nil) @@ -99,13 +96,11 @@ func (s *FirewallService) DeleteRule(w http.ResponseWriter, r *http.Request) { return } - for protocol := range slices.Values(req.Protocols) { - if err = s.firewall.Port(firewall.FireInfo{ - PortStart: req.PortStart, PortEnd: req.PortEnd, Protocol: protocol, Address: req.Address, Strategy: req.Strategy, - }, firewall.OperationRemove); err != nil { - Error(w, http.StatusInternalServerError, "%v", err) - return - } + if err = s.firewall.Port(firewall.FireInfo{ + Family: req.Family, PortStart: req.PortStart, PortEnd: req.PortEnd, Protocol: req.Protocol, Address: req.Address, Strategy: req.Strategy, Direction: req.Direction, + }, firewall.OperationRemove); err != nil { + Error(w, http.StatusInternalServerError, "%v", err) + return } Success(w, nil) diff --git a/pkg/firewall/consts.go b/pkg/firewall/consts.go index 83e819d8..56db02e6 100644 --- a/pkg/firewall/consts.go +++ b/pkg/firewall/consts.go @@ -6,7 +6,7 @@ type FireInfo struct { PortStart uint `json:"port_start"` // 1-65535 PortEnd uint `json:"port_end"` // 1-65535 Protocol string `json:"protocol"` // tcp udp tcp/udp - Strategy string `json:"strategy"` // accept drop + Strategy string `json:"strategy"` // accept drop reject Direction string `json:"direction"` // in out 入站或出站 } diff --git a/pkg/firewall/firewall.go b/pkg/firewall/firewall.go index 6f7794ec..bd527f91 100644 --- a/pkg/firewall/firewall.go +++ b/pkg/firewall/firewall.go @@ -4,6 +4,7 @@ import ( "errors" "fmt" "regexp" + "slices" "strings" "sync" @@ -28,7 +29,7 @@ type Firewall struct { func NewFirewall() *Firewall { firewall := &Firewall{ forwardListRegex: regexp.MustCompile(`^port=(\d{1,5}):proto=(.+?):toport=(\d{1,5}):toaddr=(.*)$`), - richRuleRegex: regexp.MustCompile(`^rule family="([^"]+)" (?:source address="([^"]+)" )?(?:port port="([^"]+)" )?(?:protocol="([^"]+)" )?(accept|drop|reject)$`), + richRuleRegex: regexp.MustCompile(`^rule family="([^"]+)"(?: .*?(source|destination) address="([^"]+)")?(?: .*?port port="([^"]+)")?(?: .*?protocol="([^"]+)")?.*?(accept|drop|reject)$`), } return firewall @@ -71,7 +72,9 @@ func (r *Firewall) ListRule() ([]FireInfo, error) { } item.Protocol = ruleItem[1] } + item.Family = "ipv4" item.Strategy = "accept" + item.Direction = "in" data = append(data, item) } }() @@ -131,8 +134,8 @@ func (r *Firewall) ListRichRule() ([]FireInfo, error) { if len(rule) == 0 { continue } - if itemRule, err := r.parseRichRule(rule); err == nil { - data = append(data, *itemRule) + if richRules, err := r.parseRichRule(rule); err == nil { + data = append(data, richRules) } } @@ -143,40 +146,47 @@ func (r *Firewall) Port(rule FireInfo, operation Operation) error { if rule.PortEnd == 0 { rule.PortEnd = rule.PortStart } + if rule.PortStart > rule.PortEnd { + return fmt.Errorf("invalid port range: %d-%d", rule.PortStart, rule.PortEnd) + } // 不支持的切换使用rich rules if rule.Direction != "in" || rule.Family != "ipv4" || rule.Address != "" || rule.Strategy != "accept" { return r.RichRules(rule, operation) } - stdout, err := shell.Execf("firewall-cmd --zone=public --%s-port=%d-%d/%s --permanent", operation, rule.PortStart, rule.PortEnd, rule.Protocol) - if err != nil { - return fmt.Errorf("%s port %d-%d/%s failed, err: %s", operation, rule.PortStart, rule.PortEnd, rule.Protocol, stdout) + + protocols := strings.Split(rule.Protocol, "/") + for protocol := range slices.Values(protocols) { + stdout, err := shell.Execf("firewall-cmd --zone=public --%s-port=%d-%d/%s --permanent", operation, rule.PortStart, rule.PortEnd, protocol) + if err != nil { + return fmt.Errorf("%s port %d-%d/%s failed, err: %s", operation, rule.PortStart, rule.PortEnd, protocol, stdout) + } } - _, err = shell.Execf("firewall-cmd --reload") + _, err := shell.Execf("firewall-cmd --reload") return err } func (r *Firewall) RichRules(rule FireInfo, operation Operation) error { - families := strings.Split(rule.Family, "/") // ipv4 ipv6 - - for _, family := range families { + protocols := strings.Split(rule.Protocol, "/") + for protocol := range slices.Values(protocols) { var ruleBuilder strings.Builder - ruleBuilder.WriteString(fmt.Sprintf(`rule family="%s" `, family)) + ruleBuilder.WriteString(fmt.Sprintf(`rule family="%s" `, rule.Family)) if len(rule.Address) != 0 { if rule.Direction == "in" { ruleBuilder.WriteString(fmt.Sprintf(`source address="%s" `, rule.Address)) } else if rule.Direction == "out" { ruleBuilder.WriteString(fmt.Sprintf(`destination address="%s" `, rule.Address)) - } else { - return fmt.Errorf("invalid direction: %s", rule.Direction) } } - if rule.PortStart != 0 && rule.PortEnd != 0 { + if rule.PortStart != 0 && rule.PortEnd != 0 && (rule.PortStart != 1 && rule.PortEnd != 65535) { // 1-65535是解析出来无端口规则的情况 ruleBuilder.WriteString(fmt.Sprintf(`port port="%d-%d" `, rule.PortStart, rule.PortEnd)) } - if len(rule.Protocol) != 0 { - ruleBuilder.WriteString(fmt.Sprintf(`protocol="%s" `, rule.Protocol)) + if operation == OperationRemove && protocol != "" && rule.Protocol != "tcp/udp" { // 删除操作,可以不指定协议 + ruleBuilder.WriteString(fmt.Sprintf(`protocol="%s" `, protocol)) + } + if operation == OperationAdd && protocol != "" { + ruleBuilder.WriteString(fmt.Sprintf(`protocol="%s" `, protocol)) } ruleBuilder.WriteString(rule.Strategy) @@ -213,29 +223,46 @@ func (r *Firewall) PortForward(info Forward, operation Operation) error { return err } -func (r *Firewall) parseRichRule(line string) (*FireInfo, error) { - itemRule := new(FireInfo) - if r.richRuleRegex.MatchString(line) { - match := r.richRuleRegex.FindStringSubmatch(line) - if len(match) < 6 { - return nil, errors.New("invalid rich rule") - } - - itemRule.Family = match[1] - itemRule.Address = match[2] - ports := strings.Split(match[3], "-") - if len(ports) > 1 { - itemRule.PortStart = cast.ToUint(ports[0]) - itemRule.PortEnd = cast.ToUint(ports[1]) - } else { - itemRule.PortStart = cast.ToUint(match[3]) - itemRule.PortEnd = cast.ToUint(match[3]) - } - itemRule.Protocol = match[4] - itemRule.Strategy = match[5] +func (r *Firewall) parseRichRule(line string) (FireInfo, error) { + if !r.richRuleRegex.MatchString(line) { + return FireInfo{}, errors.New("invalid rich rule format") } - return itemRule, nil + match := r.richRuleRegex.FindStringSubmatch(line) + if len(match) < 7 { + return FireInfo{}, errors.New("invalid rich rule") + } + + fireInfo := FireInfo{ + Family: match[1], + Address: match[3], + Protocol: match[5], + Strategy: match[6], + } + + if match[2] == "destination" { + fireInfo.Direction = "out" + } else { + fireInfo.Direction = "in" + } + if fireInfo.Protocol == "" { + fireInfo.Protocol = "tcp/udp" + } + + ports := strings.Split(match[4], "-") + if len(ports) == 2 { // 添加端口范围 + fireInfo.PortStart = cast.ToUint(ports[0]) + fireInfo.PortEnd = cast.ToUint(ports[1]) + } else if len(ports) == 1 && ports[0] != "" { // 添加单个端口 + port := cast.ToUint(ports[0]) + fireInfo.PortStart = port + fireInfo.PortEnd = port + } else if len(ports) == 1 && ports[0] == "" { // 未添加端口规则,表示所有端口 + fireInfo.PortStart = 1 + fireInfo.PortEnd = 65535 + } + + return fireInfo, nil } func (r *Firewall) enableForward() error { diff --git a/pkg/shell/exec.go b/pkg/shell/exec.go index 8c3cf7de..3263def2 100644 --- a/pkg/shell/exec.go +++ b/pkg/shell/exec.go @@ -8,16 +8,10 @@ import ( "os/exec" "strings" "time" - - "github.com/TheTNB/panel/pkg/slice" ) // Execf 执行 shell 命令 func Execf(shell string, args ...any) (string, error) { - if !CheckArgs(slice.ToString(args)...) { - return "", errors.New("发现危险的命令参数,中止执行") - } - var cmd *exec.Cmd _ = os.Setenv("LC_ALL", "C") cmd = exec.Command("bash", "-c", fmt.Sprintf(shell, args...)) @@ -36,10 +30,6 @@ func Execf(shell string, args ...any) (string, error) { // ExecfAsync 异步执行 shell 命令 func ExecfAsync(shell string, args ...any) error { - if !CheckArgs(slice.ToString(args)...) { - return errors.New("发现危险的命令参数,中止执行") - } - var cmd *exec.Cmd _ = os.Setenv("LC_ALL", "C") cmd = exec.Command("bash", "-c", fmt.Sprintf(shell, args...)) @@ -60,10 +50,6 @@ func ExecfAsync(shell string, args ...any) error { // ExecfWithTimeout 执行 shell 命令并设置超时时间 func ExecfWithTimeout(timeout time.Duration, shell string, args ...any) (string, error) { - if !CheckArgs(slice.ToString(args)...) { - return "", errors.New("发现危险的命令参数,中止执行") - } - var cmd *exec.Cmd _ = os.Setenv("LC_ALL", "C") cmd = exec.Command("bash", "-c", fmt.Sprintf(shell, args...)) @@ -94,21 +80,3 @@ func ExecfWithTimeout(timeout time.Duration, shell string, args ...any) (string, return strings.TrimSpace(stdout.String()), err } - -// CheckArgs 检查危险的参数 -func CheckArgs(args ...string) bool { - if len(args) == 0 { - return true - } - - dangerous := []string{"&", "|", ";", "$", "'", `"`, "(", ")", "`", "\n", "\r", ">", "<", "{", "}", "[", "]", "\\"} - for _, arg := range args { - for _, char := range dangerous { - if strings.Contains(arg, char) { - return false - } - } - } - - return true -} diff --git a/pkg/types/system.go b/pkg/types/system.go index 007a2d24..397d4b0f 100644 --- a/pkg/types/system.go +++ b/pkg/types/system.go @@ -1,13 +1,14 @@ package types import ( + "time" + "github.com/shirou/gopsutil/cpu" "github.com/shirou/gopsutil/disk" "github.com/shirou/gopsutil/host" "github.com/shirou/gopsutil/load" "github.com/shirou/gopsutil/mem" "github.com/shirou/gopsutil/net" - "time" ) // CurrentInfo 监控信息 diff --git a/web/src/api/panel/safe/index.ts b/web/src/api/panel/safe/index.ts index 3e75b8bc..8080e69d 100644 --- a/web/src/api/panel/safe/index.ts +++ b/web/src/api/panel/safe/index.ts @@ -11,12 +11,12 @@ export default { // 获取防火墙规则 firewallRules: (page: number, limit: number): Promise> => request.get('/firewall/rule', { params: { page, limit } }), - // 添加防火墙规则 - addFirewallRule: (port: number, protocol: string): Promise> => - request.post('/firewall/rule', { port, protocol }), + // 创建防火墙规则 + createFirewallRule: (rule: any): Promise> => + request.post('/firewall/rule', rule), // 删除防火墙规则 - deleteFirewallRule: (port: number, protocol: string): Promise> => - request.delete('/firewall/rule', { params: { port, protocol } }), + deleteFirewallRule: (rule: any): Promise> => + request.delete('/firewall/rule', { data: rule }), // 获取SSH ssh: (): Promise> => request.get('/safe/ssh'), // 设置SSH diff --git a/web/src/i18n/zh_CN.json b/web/src/i18n/zh_CN.json index 3b3b3a88..8aa8cb72 100644 --- a/web/src/i18n/zh_CN.json +++ b/web/src/i18n/zh_CN.json @@ -64,64 +64,6 @@ "actions": "操作" } }, - "safeIndex": { - "title": "系统安全", - "buttons": { - "delete": "删除", - "add": "添加", - "batchDelete": "批量删除" - }, - "columns": { - "port": "端口", - "protocol": "协议", - "actions": "操作" - }, - "confirm": { - "delete": "确定删除规则吗?", - "batchDelete": " 高危操作!确定删除选中的规则吗?" - }, - "alerts": { - "undelete": "取消删除", - "delete": "删除成功", - "add": "添加成功", - "setup": "设置成功", - "select": "请选择要删除的规则", - "ruleDelete": "规则 {rule} 删除成功" - }, - "filter": { - "fields": { - "firewall": { - "label": "防火墙状态", - "checked": "开启", - "unchecked": "关闭" - }, - "ssh": { - "label": "SSH状态", - "checked": "开启", - "unchecked": "关闭" - }, - "ping": { - "label": "Ping状态", - "checked": "开启", - "unchecked": "关闭" - }, - "port": { - "label": "SSH端口" - } - } - }, - "portControl": { - "title": "端口控制", - "fields": { - "port": { - "placeholder": "例如:3306, 1000-2000" - }, - "protocol": { - "placeholder": "协议" - } - } - } - }, "settingIndex": { "title": "面板设置", "info": "修改面板端口 / 入口后,需要在浏览器地址栏做相应修改方可打开面板!", diff --git a/web/src/views/app/IndexView.vue b/web/src/views/app/IndexView.vue index 6a64af6b..dedda3fb 100644 --- a/web/src/views/app/IndexView.vue +++ b/web/src/views/app/IndexView.vue @@ -228,7 +228,7 @@ onMounted(() => { @@ -338,32 +338,24 @@ onMounted(() => { - + 启动 停止 Fail2ban 会导致所有规则失效,确定停止吗? - + 重启 - + 重载 diff --git a/web/src/views/apps/frp/IndexView.vue b/web/src/views/apps/frp/IndexView.vue index f1783825..c47b525d 100644 --- a/web/src/views/apps/frp/IndexView.vue +++ b/web/src/views/apps/frp/IndexView.vue @@ -112,28 +112,20 @@ onMounted(() => { - + 启动 确定要停止 Frps 吗? - + 重启 @@ -142,7 +134,7 @@ onMounted(() => { @@ -176,28 +168,20 @@ onMounted(() => { - + 启动 确定要停止 Frpc 吗? - + 重启 @@ -206,7 +190,7 @@ onMounted(() => { diff --git a/web/src/views/apps/gitea/IndexView.vue b/web/src/views/apps/gitea/IndexView.vue index 7077958c..995b0471 100644 --- a/web/src/views/apps/gitea/IndexView.vue +++ b/web/src/views/apps/gitea/IndexView.vue @@ -82,7 +82,7 @@ onMounted(() => { type="primary" @click="handleSaveConfig" > - + 保存 @@ -101,24 +101,20 @@ onMounted(() => { - + 启动 确定要停止 Gitea 吗? - + 重启 diff --git a/web/src/views/apps/mysql/IndexView.vue b/web/src/views/apps/mysql/IndexView.vue index 0405754d..a3cee872 100644 --- a/web/src/views/apps/mysql/IndexView.vue +++ b/web/src/views/apps/mysql/IndexView.vue @@ -154,7 +154,7 @@ onMounted(() => { type="primary" @click="handleSaveConfig" > - + 保存 { type="primary" @click="handleClearErrorLog" > - + 清空日志 { type="primary" @click="handleClearSlowLog" > - + 清空慢日志 @@ -192,32 +192,24 @@ onMounted(() => { - + 启动 停止 MySQL 会导致使用 MySQL 的网站无法访问,确定要停止吗? - + 重启 - + 重载 diff --git a/web/src/views/apps/nginx/IndexView.vue b/web/src/views/apps/nginx/IndexView.vue index 02f50bdf..4448c534 100644 --- a/web/src/views/apps/nginx/IndexView.vue +++ b/web/src/views/apps/nginx/IndexView.vue @@ -125,7 +125,7 @@ onMounted(() => { type="primary" @click="handleSaveConfig" > - + 保存 { type="primary" @click="handleClearErrorLog" > - + 清空日志 @@ -153,28 +153,24 @@ onMounted(() => { - + 启动 停止 OpenResty 会导致所有网站无法访问,确定要停止吗? - + 重启 - + 重载 diff --git a/web/src/views/apps/php/IndexView.vue b/web/src/views/apps/php/IndexView.vue index 1f0f1937..99978620 100644 --- a/web/src/views/apps/php/IndexView.vue +++ b/web/src/views/apps/php/IndexView.vue @@ -242,7 +242,7 @@ onMounted(() => { type="primary" @click="handleSaveConfig" > - + 保存 { type="primary" @click="handleSaveFPMConfig" > - + 保存 { type="primary" @click="handleClearErrorLog" > - + 清空错误日志 { type="primary" @click="handleClearSlowLog" > - + 清空慢日志 @@ -289,32 +289,24 @@ onMounted(() => { - + 启动 停止 PHP {{ version }} 会导致使用 PHP {{ version }} 的网站无法访问,确定要停止吗? - + 重启 - + 重载 diff --git a/web/src/views/apps/phpmyadmin/IndexView.vue b/web/src/views/apps/phpmyadmin/IndexView.vue index 776c362b..7f9c9d07 100644 --- a/web/src/views/apps/phpmyadmin/IndexView.vue +++ b/web/src/views/apps/phpmyadmin/IndexView.vue @@ -50,7 +50,7 @@ onMounted(() => { diff --git a/web/src/views/apps/podman/IndexView.vue b/web/src/views/apps/podman/IndexView.vue index 53fafa6b..832e0711 100644 --- a/web/src/views/apps/podman/IndexView.vue +++ b/web/src/views/apps/podman/IndexView.vue @@ -91,7 +91,7 @@ onMounted(() => { type="primary" @click="handleSaveRegistryConfig" > - + 保存 { type="primary" @click="handleSaveStorageConfig" > - + 保存 @@ -123,28 +123,20 @@ onMounted(() => { - + 启动 确定要停止 Podman 吗? - + 重启 diff --git a/web/src/views/apps/postgresql/IndexView.vue b/web/src/views/apps/postgresql/IndexView.vue index 6d0ba840..1857ab7a 100644 --- a/web/src/views/apps/postgresql/IndexView.vue +++ b/web/src/views/apps/postgresql/IndexView.vue @@ -136,7 +136,7 @@ onMounted(() => { type="primary" @click="handleSaveConfig" > - + 保存 { type="primary" @click="handleSaveUserConfig" > - + 保存 - + 清空日志 @@ -169,32 +169,24 @@ onMounted(() => { - + 启动 停止 PostgreSQL 会导致使用 PostgreSQL 的网站无法访问,确定要停止吗? - + 重启 - + 重载 diff --git a/web/src/views/apps/pureftpd/IndexView.vue b/web/src/views/apps/pureftpd/IndexView.vue index 906a18cb..30cf7a92 100644 --- a/web/src/views/apps/pureftpd/IndexView.vue +++ b/web/src/views/apps/pureftpd/IndexView.vue @@ -222,7 +222,7 @@ onMounted(() => { @@ -251,28 +251,20 @@ onMounted(() => { - + 启动 停止 Pure-Ftpd 会导致无法使用 FTP 服务,确定要停止吗? - + 重启 diff --git a/web/src/views/apps/redis/IndexView.vue b/web/src/views/apps/redis/IndexView.vue index 135428ba..915cf8c5 100644 --- a/web/src/views/apps/redis/IndexView.vue +++ b/web/src/views/apps/redis/IndexView.vue @@ -100,7 +100,7 @@ onMounted(() => { type="primary" @click="handleSaveConfig" > - + 保存 @@ -120,28 +120,20 @@ onMounted(() => { - + 启动 停止 Redis 会导致使用 Redis 的网站无法访问,确定要停止吗? - + 重启 diff --git a/web/src/views/apps/rsync/IndexView.vue b/web/src/views/apps/rsync/IndexView.vue index 34149c29..fea812de 100644 --- a/web/src/views/apps/rsync/IndexView.vue +++ b/web/src/views/apps/rsync/IndexView.vue @@ -244,7 +244,7 @@ onMounted(() => { type="primary" @click="handleSaveConfig" > - + 保存 { type="primary" @click="addModuleModal = true" > - + 添加模块 @@ -273,28 +273,20 @@ onMounted(() => { - + 启动 停止 Rsync 服务后,将无法使用 Rsync 功能,确定要停止吗? - + 重启 diff --git a/web/src/views/apps/s3fs/IndexView.vue b/web/src/views/apps/s3fs/IndexView.vue index 073e9977..8b37a63b 100644 --- a/web/src/views/apps/s3fs/IndexView.vue +++ b/web/src/views/apps/s3fs/IndexView.vue @@ -116,7 +116,7 @@ onMounted(() => { diff --git a/web/src/views/apps/supervisor/IndexView.vue b/web/src/views/apps/supervisor/IndexView.vue index 95ef0de3..63d5962c 100644 --- a/web/src/views/apps/supervisor/IndexView.vue +++ b/web/src/views/apps/supervisor/IndexView.vue @@ -368,7 +368,7 @@ onUnmounted(() => { type="primary" @click="handleSaveConfig" > - + 保存 { type="primary" @click="addProcessModal = true" > - + 添加进程 - + 清空日志 @@ -401,32 +401,24 @@ onUnmounted(() => { - + 启动 停止 Supervisor 会导致 Supervisor 管理的所有进程被杀死,确定要停止吗? - + 重启 - + 重载 diff --git a/web/src/views/apps/toolbox/IndexView.vue b/web/src/views/apps/toolbox/IndexView.vue index c6688e75..53269b7d 100644 --- a/web/src/views/apps/toolbox/IndexView.vue +++ b/web/src/views/apps/toolbox/IndexView.vue @@ -82,15 +82,15 @@ onMounted(() => { diff --git a/web/src/views/backup/IndexView.vue b/web/src/views/backup/IndexView.vue index edc74524..131ab066 100644 --- a/web/src/views/backup/IndexView.vue +++ b/web/src/views/backup/IndexView.vue @@ -30,7 +30,7 @@ const handleCreate = () => {