mirror of
https://github.com/tnb-labs/panel.git
synced 2026-08-31 20:05:34 +08:00
Compare commits
120 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| a91d0b79a7 | |||
| f0a9aceb13 | |||
| c251f73895 | |||
| 79b8e58412 | |||
| 73be25dcf7 | |||
| fff4d3eae2 | |||
| e614e97312 | |||
| 7ac448d2c4 | |||
| 08f5c88cee | |||
| 779d734dad | |||
| c3ca61a665 | |||
| 832367eb2a | |||
| 929a799f68 | |||
| f1cdb19a59 | |||
| 6f588efea7 | |||
| 333e8ae39f | |||
| 12dc49968a | |||
| 960fc78518 | |||
| 447c393b46 | |||
| a72eb2ba43 | |||
| 6cff72de98 | |||
| 89be5e077a | |||
| 3e1caa4f2e | |||
| 459b71e8cb | |||
| 8c8a957df1 | |||
| 9648b24d58 | |||
| b5752ac9e5 | |||
| 6e8cb1d513 | |||
| 191c3d8b3f | |||
| 657382f929 | |||
| a64ec36744 | |||
| c527af97ca | |||
| 2293646c4c | |||
| 23e215b009 | |||
| a07c50b3f5 | |||
| 9956824d54 | |||
| 6ac5e63684 | |||
| 23b13ff79d | |||
| 4a7742b991 | |||
| 377b904459 | |||
| b30d476a59 | |||
| 3e7629b5b1 | |||
| 32bda21196 | |||
| d27a29151e | |||
| 2b74b35701 | |||
| 30b1cf28cb | |||
| 2d17de5266 | |||
| 01eb10bda3 | |||
| 86376503ac | |||
| 39fd752825 | |||
| 0b6eed5fed | |||
| 9a81c77167 | |||
| 03c375e7d9 | |||
| 645e6d663f | |||
| 2b112d735f | |||
| 4632cf7d58 | |||
| b15262b5ce | |||
| b25456e2fa | |||
| 398bdce676 | |||
| d25c035fc0 | |||
| 486cbe047b | |||
| 06d620ac06 | |||
| aa661972cc | |||
| 74261f4045 | |||
| 50ec26ef03 | |||
| dff6d27e04 | |||
| e3703975ee | |||
| 0cd49a3b18 | |||
| 1ad51e0fa0 | |||
| 405d8390bb | |||
| c4727dca27 | |||
| 19d1169491 | |||
| e95fb840f7 | |||
| 2e0def62ba | |||
| a4d12f8590 | |||
| 8a2c2411af | |||
| e79d4b43cc | |||
| 169b8c74f7 | |||
| 68eb239619 | |||
| 93f4797d44 | |||
| 170453e5ec | |||
| 6e44504378 | |||
| 27c851ba8e | |||
| 03c71a3fe6 | |||
| 95d88cc9a8 | |||
| db909f1235 | |||
| 27c0451d00 | |||
| 6b66552350 | |||
| c873f850bb | |||
| 61b93c81e6 | |||
| 7181390d94 | |||
| 2a9a6301ac | |||
| 22222f0fd7 | |||
| 74380a5d37 | |||
| 43764cf364 | |||
| 6cec736467 | |||
| d9138ddf89 | |||
| 73c2c31ce6 | |||
| f6bd27a0cb | |||
| 47df0ab396 | |||
| 35d7049bc1 | |||
| 438f7fd458 | |||
| 5cc2ae1a32 | |||
| f4af1319c9 | |||
| c966920e29 | |||
| a80b0ff8d4 | |||
| c1ed51767a | |||
| 7b8575b6dd | |||
| 48c41c7fd5 | |||
| 16791f3acb | |||
| 34e00731b5 | |||
| c54bff44cb | |||
| 3b738406c6 | |||
| 3f83119b39 | |||
| 0eae148737 | |||
| 7a648097d2 | |||
| 6de5e799ea | |||
| 36d7575f0b | |||
| 48a49db67b | |||
| a573a6e44f |
@@ -1,7 +1,6 @@
|
||||
name: 🐛 报告问题 (Bug Report)
|
||||
name: ☢️ 报告问题 (Bug Report)
|
||||
description: 创建一个报告以帮助我们改进 (Create a report to help us improve)
|
||||
title: "🐛 [Bug] "
|
||||
labels: [ "☢️ Bug", "bug" ]
|
||||
type: ☢️ Bug
|
||||
|
||||
body:
|
||||
- type: markdown
|
||||
@@ -42,7 +41,7 @@ body:
|
||||
description: |
|
||||
请提供面板的版本号。
|
||||
Please provide the version number of the panel.
|
||||
placeholder: "2.3.0"
|
||||
placeholder: "2.4.0"
|
||||
validations:
|
||||
required: true
|
||||
- type: textarea
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
name: ✨ 功能请求 (Feature Request)
|
||||
description: 为这个项目提出一个想法 (Suggest an idea for this project)
|
||||
title: "✨ [Feature] "
|
||||
labels: [ "✏️ Feature", "enhancement" ]
|
||||
type: ✨ Feature
|
||||
|
||||
body:
|
||||
- type: markdown
|
||||
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 12 KiB |
@@ -40,6 +40,8 @@ jobs:
|
||||
run: |
|
||||
echo "GOVERSION=$(go version | cut -d' ' -f3)" >> $GITHUB_ENV
|
||||
echo "HOSTNAME=$(hostname)" >> $GITHUB_ENV
|
||||
- name: Clear node_modules
|
||||
run: rm -rf node_modules
|
||||
- name: Run GoReleaser
|
||||
uses: goreleaser/goreleaser-action@v6
|
||||
with:
|
||||
|
||||
+1
-1
@@ -60,7 +60,7 @@ archives:
|
||||
builds:
|
||||
- web
|
||||
- cli
|
||||
format: zip
|
||||
formats: ["zip", "tar.gz", "tar.xz"]
|
||||
wrap_in_directory: false
|
||||
strip_binary_directory: true
|
||||
files:
|
||||
|
||||
@@ -15,7 +15,7 @@
|
||||
|
||||
</div>
|
||||
|
||||
企业级全能服务器运维管理面板。简单轻量,高效运维。
|
||||
新一代全能服务器运维管理面板。简单轻量,高效运维。
|
||||
|
||||
官网:[panel.haozi.net](https://panel.haozi.net) | QQ群:[12370907](https://jq.qq.com/?_wv=1027&k=I1oJKSTH) | 微信群:[复制此链接](https://work.weixin.qq.com/gm/d8ebf618553398d454e3378695c858b6)
|
||||
|
||||
@@ -59,6 +59,9 @@
|
||||
<a href="https://scdn.ddunyun.com/">
|
||||
<img height="80" src=".github/assets/ddunyun.png" alt="盾云SCDN">
|
||||
</a>
|
||||
<a href="https://hongtoutong.com">
|
||||
<img height="80" src=".github/assets/htt.png" alt="红透通">
|
||||
</a>
|
||||
<a href="https://1ms.run">
|
||||
<img height="80" src=".github/assets/1ms.svg" alt="毫秒镜像提供经过审核的 Docker 镜像加速服务">
|
||||
</a>
|
||||
|
||||
+4
-1
@@ -15,7 +15,7 @@
|
||||
|
||||
</div>
|
||||
|
||||
Enterprise-level all-in-one server operation and maintenance management panel. Simple and lightweight, efficient operation and maintenance.
|
||||
A new generation of all-in-one server operation and maintenance management panel. Simple and lightweight, efficient operation and maintenance.
|
||||
|
||||
Website: [panel.haozi.net](https://panel.haozi.net) | QQ group: [12370907](https://jq.qq.com/?_wv=1027&k=I1oJKSTH) | WeChat group: [Copy this link](https://work.weixin.qq.com/gm/d8ebf618553398d454e3378695c858b6)
|
||||
|
||||
@@ -59,6 +59,9 @@ If the Rat Panel is helpful to you, welcome to sponsor us, also thanks to the fo
|
||||
<a href="https://scdn.ddunyun.com/">
|
||||
<img height="80" src=".github/assets/ddunyun.png" alt="盾云SCDN">
|
||||
</a>
|
||||
<a href="https://hongtoutong.com">
|
||||
<img height="80" src=".github/assets/htt.png" alt="红透通">
|
||||
</a>
|
||||
<a href="https://1ms.run">
|
||||
<img height="80" src=".github/assets/1ms.svg" alt="毫秒镜像提供经过审核的 Docker 镜像加速服务">
|
||||
</a>
|
||||
|
||||
+1
-1
@@ -144,7 +144,7 @@ func initWeb() (*app.Web, error) {
|
||||
return nil, err
|
||||
}
|
||||
gormigrate := bootstrap.NewMigrate(db)
|
||||
jobs := job.NewJobs(db, logger, settingRepo, certRepo, backupRepo, cacheRepo)
|
||||
jobs := job.NewJobs(db, logger, settingRepo, certRepo, backupRepo, cacheRepo, taskRepo)
|
||||
cron, err := bootstrap.NewCron(koanf, logger, jobs)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
|
||||
@@ -1,20 +1,20 @@
|
||||
module github.com/tnb-labs/panel
|
||||
|
||||
go 1.23
|
||||
go 1.24
|
||||
|
||||
require (
|
||||
github.com/bddjr/hlfhr v1.3.6
|
||||
github.com/bddjr/hlfhr v1.3.8
|
||||
github.com/beevik/ntp v1.4.3
|
||||
github.com/creack/pty v1.1.24
|
||||
github.com/expr-lang/expr v1.16.9
|
||||
github.com/glebarez/sqlite v1.11.0
|
||||
github.com/go-chi/chi/v5 v5.2.0
|
||||
github.com/go-chi/chi/v5 v5.2.1
|
||||
github.com/go-gormigrate/gormigrate/v2 v2.1.3
|
||||
github.com/go-rat/chix v1.1.4
|
||||
github.com/go-rat/gormstore v1.0.6
|
||||
github.com/go-rat/sessions v1.0.11
|
||||
github.com/go-rat/utils v1.0.7
|
||||
github.com/go-resty/resty/v2 v2.16.2
|
||||
github.com/go-rat/sessions v1.0.14
|
||||
github.com/go-rat/utils v1.0.9
|
||||
github.com/go-resty/resty/v2 v2.16.5
|
||||
github.com/go-sql-driver/mysql v1.8.1
|
||||
github.com/golang-cz/httplog v0.0.0-20241002114323-98e09d6f537a
|
||||
github.com/gomodule/redigo v1.9.2
|
||||
@@ -30,19 +30,19 @@ require (
|
||||
github.com/libdns/cloudflare v0.1.1
|
||||
github.com/libdns/huaweicloud v0.3.1
|
||||
github.com/libdns/libdns v0.2.2
|
||||
github.com/libdns/tencentcloud v1.1.0
|
||||
github.com/mholt/acmez/v3 v3.0.0
|
||||
github.com/libdns/tencentcloud v1.2.0
|
||||
github.com/mholt/acmez/v3 v3.0.1
|
||||
github.com/orandin/slog-gorm v1.4.0
|
||||
github.com/robfig/cron/v3 v3.0.1
|
||||
github.com/samber/lo v1.47.0
|
||||
github.com/samber/lo v1.49.1
|
||||
github.com/sethvargo/go-limiter v1.0.0
|
||||
github.com/shirou/gopsutil v2.21.11+incompatible
|
||||
github.com/shirou/gopsutil v3.21.11+incompatible
|
||||
github.com/spf13/cast v1.7.1
|
||||
github.com/stretchr/testify v1.10.0
|
||||
github.com/tufanbarisyildirim/gonginx v0.0.0-20241225173012-5cc15aab65bd
|
||||
github.com/tufanbarisyildirim/gonginx v0.0.0-20250120210832-12a9c7ae0c8a
|
||||
github.com/urfave/cli/v3 v3.0.0-beta1
|
||||
golang.org/x/crypto v0.31.0
|
||||
golang.org/x/net v0.33.0
|
||||
golang.org/x/crypto v0.33.0
|
||||
golang.org/x/net v0.35.0
|
||||
gopkg.in/natefinch/lumberjack.v2 v2.2.1
|
||||
gopkg.in/yaml.v3 v3.0.1
|
||||
gorm.io/gorm v1.25.12
|
||||
@@ -52,11 +52,11 @@ require (
|
||||
filippo.io/edwards25519 v1.1.0 // indirect
|
||||
github.com/davecgh/go-spew v1.1.1 // indirect
|
||||
github.com/dustin/go-humanize v1.0.1 // indirect
|
||||
github.com/fsnotify/fsnotify v1.7.0 // indirect
|
||||
github.com/gabriel-vasile/mimetype v1.4.6 // indirect
|
||||
github.com/fsnotify/fsnotify v1.8.0 // indirect
|
||||
github.com/gabriel-vasile/mimetype v1.4.8 // indirect
|
||||
github.com/glebarez/go-sqlite v1.22.0 // indirect
|
||||
github.com/go-ole/go-ole v1.2.6 // indirect
|
||||
github.com/go-rat/securecookie v1.0.1 // indirect
|
||||
github.com/go-ole/go-ole v1.3.0 // indirect
|
||||
github.com/go-rat/securecookie v1.1.0 // indirect
|
||||
github.com/go-viper/mapstructure/v2 v2.2.1 // indirect
|
||||
github.com/gofiber/schema v1.2.0 // indirect
|
||||
github.com/google/uuid v1.6.0 // indirect
|
||||
@@ -70,25 +70,23 @@ require (
|
||||
github.com/mitchellh/copystructure v1.2.0 // indirect
|
||||
github.com/mitchellh/reflectwalk v1.0.2 // indirect
|
||||
github.com/ncruces/go-strftime v0.1.9 // indirect
|
||||
github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e // indirect
|
||||
github.com/pmezard/go-difflib v1.0.0 // indirect
|
||||
github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec // indirect
|
||||
github.com/stretchr/objx v0.5.2 // indirect
|
||||
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common v1.0.1051 // indirect
|
||||
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common v1.0.1096 // indirect
|
||||
github.com/tklauser/go-sysconf v0.3.14 // indirect
|
||||
github.com/tklauser/numcpus v0.8.0 // indirect
|
||||
github.com/tklauser/numcpus v0.9.0 // indirect
|
||||
github.com/yusufpapurcu/wmi v1.2.4 // indirect
|
||||
golang.org/x/exp v0.0.0-20240909161429-701f63a606c0 // indirect
|
||||
golang.org/x/sys v0.28.0 // indirect
|
||||
golang.org/x/text v0.21.0 // indirect
|
||||
gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f // indirect
|
||||
modernc.org/libc v1.60.1 // indirect
|
||||
modernc.org/mathutil v1.6.0 // indirect
|
||||
modernc.org/memory v1.8.0 // indirect
|
||||
modernc.org/sqlite v1.32.0 // indirect
|
||||
golang.org/x/exp v0.0.0-20250210185358-939b2ce775ac // indirect
|
||||
golang.org/x/sys v0.30.0 // indirect
|
||||
golang.org/x/text v0.22.0 // indirect
|
||||
modernc.org/libc v1.61.13 // indirect
|
||||
modernc.org/mathutil v1.7.1 // indirect
|
||||
modernc.org/memory v1.8.2 // indirect
|
||||
modernc.org/sqlite v1.34.5 // indirect
|
||||
)
|
||||
|
||||
replace (
|
||||
github.com/libdns/tencentcloud => github.com/devhaozi/tencentcloud v0.0.0-20241129095955-7d4e898ce504
|
||||
github.com/mholt/acmez/v3 => github.com/tnb-labs/acmez/v3 v3.0.0-20241217024017-a2f2c48efdcc
|
||||
github.com/mholt/acmez/v3 => github.com/tnb-labs/acmez/v3 v3.0.0-20250101070450-67fb7b3d86d1
|
||||
)
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
filippo.io/edwards25519 v1.1.0 h1:FNf4tywRC1HmFuKW5xopWpigGjJKiJSV0Cqo0cJWDaA=
|
||||
filippo.io/edwards25519 v1.1.0/go.mod h1:BxyFTGdWcka3PhytdK4V28tE5sGfRvvvRV7EaN4VDT4=
|
||||
github.com/bddjr/hlfhr v1.3.6 h1:XautNR6Vomud8SGh1V1Yjoj1L4YblsNM0ZUwZ7r3q4U=
|
||||
github.com/bddjr/hlfhr v1.3.6/go.mod h1:oyIv4Q9JpCgZFdtH3KyTNWp7YYRWl4zl8k4ozrMAB4g=
|
||||
github.com/bddjr/hlfhr v1.3.8 h1:QQ6KYgtnBbvYvCWuu/tOnBZamKAPtJzesj2qbjgyn7o=
|
||||
github.com/bddjr/hlfhr v1.3.8/go.mod h1:oyIv4Q9JpCgZFdtH3KyTNWp7YYRWl4zl8k4ozrMAB4g=
|
||||
github.com/beevik/ntp v1.4.3 h1:PlbTvE5NNy4QHmA4Mg57n7mcFTmr1W1j3gcK7L1lqho=
|
||||
github.com/beevik/ntp v1.4.3/go.mod h1:Unr8Zg+2dRn7d8bHFuehIMSvvUYssHMxW3Q5Nx4RW5Q=
|
||||
github.com/creack/pty v1.1.24 h1:bJrF4RRfyJnbTJqzRLHzcGaZK1NeM5kTC9jGgovnR1s=
|
||||
@@ -16,32 +16,33 @@ github.com/expr-lang/expr v1.16.9 h1:WUAzmR0JNI9JCiF0/ewwHB1gmcGw5wW7nWt8gc6PpCI
|
||||
github.com/expr-lang/expr v1.16.9/go.mod h1:8/vRC7+7HBzESEqt5kKpYXxrxkr31SaO8r40VO/1IT4=
|
||||
github.com/frankban/quicktest v1.14.6 h1:7Xjx+VpznH+oBnejlPUj8oUpdxnVs4f8XU8WnHkI4W8=
|
||||
github.com/frankban/quicktest v1.14.6/go.mod h1:4ptaffx2x8+WTWXmUCuVU6aPUX1/Mz7zb5vbUoiM6w0=
|
||||
github.com/fsnotify/fsnotify v1.7.0 h1:8JEhPFa5W2WU7YfeZzPNqzMP6Lwt7L2715Ggo0nosvA=
|
||||
github.com/fsnotify/fsnotify v1.7.0/go.mod h1:40Bi/Hjc2AVfZrqy+aj+yEI+/bRxZnMJyTJwOpGvigM=
|
||||
github.com/gabriel-vasile/mimetype v1.4.6 h1:3+PzJTKLkvgjeTbts6msPJt4DixhT4YtFNf1gtGe3zc=
|
||||
github.com/gabriel-vasile/mimetype v1.4.6/go.mod h1:JX1qVKqZd40hUPpAfiNTe0Sne7hdfKSbOqqmkq8GCXc=
|
||||
github.com/fsnotify/fsnotify v1.8.0 h1:dAwr6QBTBZIkG8roQaJjGof0pp0EeF+tNV7YBP3F/8M=
|
||||
github.com/fsnotify/fsnotify v1.8.0/go.mod h1:8jBTzvmWwFyi3Pb8djgCCO5IBqzKJ/Jwo8TRcHyHii0=
|
||||
github.com/gabriel-vasile/mimetype v1.4.8 h1:FfZ3gj38NjllZIeJAmMhr+qKL8Wu+nOoI3GqacKw1NM=
|
||||
github.com/gabriel-vasile/mimetype v1.4.8/go.mod h1:ByKUIKGjh1ODkGM1asKUbQZOLGrPjydw3hYPU2YU9t8=
|
||||
github.com/glebarez/go-sqlite v1.22.0 h1:uAcMJhaA6r3LHMTFgP0SifzgXg46yJkgxqyuyec+ruQ=
|
||||
github.com/glebarez/go-sqlite v1.22.0/go.mod h1:PlBIdHe0+aUEFn+r2/uthrWq4FxbzugL0L8Li6yQJbc=
|
||||
github.com/glebarez/sqlite v1.11.0 h1:wSG0irqzP6VurnMEpFGer5Li19RpIRi2qvQz++w0GMw=
|
||||
github.com/glebarez/sqlite v1.11.0/go.mod h1:h8/o8j5wiAsqSPoWELDUdJXhjAhsVliSn7bWZjOhrgQ=
|
||||
github.com/go-chi/chi/v5 v5.2.0 h1:Aj1EtB0qR2Rdo2dG4O94RIU35w2lvQSj6BRA4+qwFL0=
|
||||
github.com/go-chi/chi/v5 v5.2.0/go.mod h1:DslCQbL2OYiznFReuXYUmQ2hGd1aDpCnlMNITLSKoi8=
|
||||
github.com/go-chi/chi/v5 v5.2.1 h1:KOIHODQj58PmL80G2Eak4WdvUzjSJSm0vG72crDCqb8=
|
||||
github.com/go-chi/chi/v5 v5.2.1/go.mod h1:L2yAIGWB3H+phAw1NxKwWM+7eUH/lU8pOMm5hHcoops=
|
||||
github.com/go-gormigrate/gormigrate/v2 v2.1.3 h1:ei3Vq/rpPI/jCJY9mRHJAKg5vU+EhZyWhBAkaAomQuw=
|
||||
github.com/go-gormigrate/gormigrate/v2 v2.1.3/go.mod h1:VJ9FIOBAur+NmQ8c4tDVwOuiJcgupTG105FexPFrXzA=
|
||||
github.com/go-ole/go-ole v1.2.6 h1:/Fpf6oFPoeFik9ty7siob0G6Ke8QvQEuVcuChpwXzpY=
|
||||
github.com/go-ole/go-ole v1.2.6/go.mod h1:pprOEPIfldk/42T2oK7lQ4v4JSDwmV0As9GaiUsvbm0=
|
||||
github.com/go-ole/go-ole v1.3.0 h1:Dt6ye7+vXGIKZ7Xtk4s6/xVdGDQynvom7xCFEdWr6uE=
|
||||
github.com/go-ole/go-ole v1.3.0/go.mod h1:5LS6F96DhAwUc7C+1HLexzMXY1xGRSryjyPPKW6zv78=
|
||||
github.com/go-rat/chix v1.1.4 h1:YVDwF4vrlkm5hmlDGWKoiWPgP98pJooBvhsto8UWq+o=
|
||||
github.com/go-rat/chix v1.1.4/go.mod h1:eKUTG7GXqMS278PH0QZi8yMWZddvMfxqWu7mverM6kQ=
|
||||
github.com/go-rat/gormstore v1.0.6 h1:YxmaY6n3JoTk6o9RXoZ1+cQ6HQL+ayf/6d8D76ydCAc=
|
||||
github.com/go-rat/gormstore v1.0.6/go.mod h1:xG/n+Du8baWf7ptiafiHLWBZWVXrYIPC42CsoEbfr4M=
|
||||
github.com/go-rat/securecookie v1.0.1 h1:HW0fpKmB+FjJzXTw8ABOwBJ+XrPmRBSZqHhmrv86lBo=
|
||||
github.com/go-rat/securecookie v1.0.1/go.mod h1:tP/ObWYyjmcpabQ7WTon/i2lBSip/Aolliw2llXuPDU=
|
||||
github.com/go-rat/sessions v1.0.11 h1:2eTUvhEBtymrAtwv71LlGHNylz+Ad2SgY3jg/sSUboA=
|
||||
github.com/go-rat/sessions v1.0.11/go.mod h1:Ray/GCbuhm4U9xpjFFSCfOTCEn91puEhAXX5creHE9g=
|
||||
github.com/go-rat/utils v1.0.7 h1:hZUe+n1W/tvF3j+oP/TeAHX3AF98SjVB1FuF11zkCAI=
|
||||
github.com/go-rat/utils v1.0.7/go.mod h1:b0S/vd2bXWvPUQpw8z6RmJrUG7G7BkMuNSrsz6JRBHs=
|
||||
github.com/go-resty/resty/v2 v2.16.2 h1:CpRqTjIzq/rweXUt9+GxzzQdlkqMdt8Lm/fuK/CAbAg=
|
||||
github.com/go-resty/resty/v2 v2.16.2/go.mod h1:0fHAoK7JoBy/Ch36N8VFeMsK7xQOHhvWaC3iOktwmIU=
|
||||
github.com/go-rat/securecookie v1.1.0 h1:bvwE9n6X3a4eazOIevEvZghkvZ3OpY4BX1cnH/1/x0s=
|
||||
github.com/go-rat/securecookie v1.1.0/go.mod h1:Z870TcL7ktAjRuhPeQXYuQcA6/DdzKwwqSwDQuPmufI=
|
||||
github.com/go-rat/sessions v1.0.14 h1:YSzlGkKzsZEUIJj2s8ZEH4DcOqScm6htIVEOvH2lvd0=
|
||||
github.com/go-rat/sessions v1.0.14/go.mod h1:jqpYqyMKZQl239GQ5W5LFRZUUQMGoNX9w7+zTQA7Soc=
|
||||
github.com/go-rat/utils v1.0.9 h1:16zq6CpeULJgoW+TaJZ+gS4EPl0tQYAcuAdx3/GNCNs=
|
||||
github.com/go-rat/utils v1.0.9/go.mod h1:LhzbrdsTHIo6Rjlz27Nh8edkugmoxbZjN87iV+ch+5M=
|
||||
github.com/go-resty/resty/v2 v2.16.5 h1:hBKqmWrr7uRc3euHVqmh1HTHcKn99Smr7o5spptdhTM=
|
||||
github.com/go-resty/resty/v2 v2.16.5/go.mod h1:hkJtXbA2iKHzJheXYvQ8snQES5ZLGKMwQ07xAwp/fiA=
|
||||
github.com/go-sql-driver/mysql v1.8.1 h1:LedoTUt/eveggdHS9qUFC1EFSa8bU2+1pZjSRpvNJ1Y=
|
||||
github.com/go-sql-driver/mysql v1.8.1/go.mod h1:wEBSXgmK//2ZFJyE+qWnIsVGmvmEKlqwuVSjsCm7DZg=
|
||||
github.com/go-viper/mapstructure/v2 v2.2.1 h1:ZAaOCxANMuZx5RCeg0mBdEZk7DZasvvZIxtHqx8aGss=
|
||||
@@ -92,8 +93,6 @@ github.com/knadh/koanf/v2 v2.1.2 h1:I2rtLRqXRy1p01m/utEtpZSSA6dcJbgGVuE27kW2PzQ=
|
||||
github.com/knadh/koanf/v2 v2.1.2/go.mod h1:Gphfaen0q1Fc1HTgJgSTC4oRX9R2R5ErYMZJy8fLJBo=
|
||||
github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE=
|
||||
github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk=
|
||||
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
|
||||
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
|
||||
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
|
||||
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
|
||||
github.com/lib/pq v1.10.9 h1:YXG7RB+JIjhP29X+OtkiDnYaXQwpS4JEWq7dtCCRUEw=
|
||||
@@ -127,28 +126,28 @@ github.com/robfig/cron/v3 v3.0.1 h1:WdRxkvbJztn8LMz/QEvLN5sBU+xKpSqwwUO1Pjr4qDs=
|
||||
github.com/robfig/cron/v3 v3.0.1/go.mod h1:eQICP3HwyT7UooqI/z+Ov+PtYAWygg1TEWWzGIFLtro=
|
||||
github.com/rogpeppe/go-internal v1.9.0 h1:73kH8U+JUqXU8lRuOHeVHaa/SZPifC7BkcraZVejAe8=
|
||||
github.com/rogpeppe/go-internal v1.9.0/go.mod h1:WtVeX8xhTBvf0smdhujwtBcq4Qrzq/fJaraNFVN+nFs=
|
||||
github.com/samber/lo v1.47.0 h1:z7RynLwP5nbyRscyvcD043DWYoOcYRv3mV8lBeqOCLc=
|
||||
github.com/samber/lo v1.47.0/go.mod h1:RmDH9Ct32Qy3gduHQuKJ3gW1fMHAnE/fAzQuf6He5cU=
|
||||
github.com/samber/lo v1.49.1 h1:4BIFyVfuQSEpluc7Fua+j1NolZHiEHEpaSEKdsH0tew=
|
||||
github.com/samber/lo v1.49.1/go.mod h1:dO6KHFzUKXgP8LDhU0oI8d2hekjXnGOu0DB8Jecxd6o=
|
||||
github.com/sethvargo/go-limiter v1.0.0 h1:JqW13eWEMn0VFv86OKn8wiYJY/m250WoXdrjRV0kLe4=
|
||||
github.com/sethvargo/go-limiter v1.0.0/go.mod h1:01b6tW25Ap+MeLYBuD4aHunMrJoNO5PVUFdS9rac3II=
|
||||
github.com/shirou/gopsutil v2.21.11+incompatible h1:lOGOyCG67a5dv2hq5Z1BLDUqqKp3HkbjPcz5j6XMS0U=
|
||||
github.com/shirou/gopsutil v2.21.11+incompatible/go.mod h1:5b4v6he4MtMOwMlS0TUMTu2PcXUg8+E1lC7eC3UO/RA=
|
||||
github.com/shirou/gopsutil v3.21.11+incompatible h1:+1+c1VGhc88SSonWP6foOcLhvnKlUeu/erjjvaPEYiI=
|
||||
github.com/shirou/gopsutil v3.21.11+incompatible/go.mod h1:5b4v6he4MtMOwMlS0TUMTu2PcXUg8+E1lC7eC3UO/RA=
|
||||
github.com/spf13/cast v1.7.1 h1:cuNEagBQEHWN1FnbGEjCXL2szYEXqfJPbP2HNUaca9Y=
|
||||
github.com/spf13/cast v1.7.1/go.mod h1:ancEpBxwJDODSW/UG4rDrAqiKolqNNh2DX3mk86cAdo=
|
||||
github.com/stretchr/objx v0.5.2 h1:xuMeJ0Sdp5ZMRXx/aWO6RZxdr3beISkG5/G/aIRr3pY=
|
||||
github.com/stretchr/objx v0.5.2/go.mod h1:FRsXN1f5AsAjCGJKqEizvkpNtU+EGNCLh3NxZ/8L+MA=
|
||||
github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA=
|
||||
github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
|
||||
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common v1.0.1051 h1:3mg0L9vv9eO8UN4Oa7vNawe6yUIuXf9D0Q79rUmnblo=
|
||||
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common v1.0.1051/go.mod h1:r5r4xbfxSaeR04b166HGsBa/R4U3SueirEUpXGuw+Q0=
|
||||
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common v1.0.1096 h1:DMokC7T0UF8wMfT1kD+mX3M+hc2C06gmFvQ9gsfRPmI=
|
||||
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common v1.0.1096/go.mod h1:r5r4xbfxSaeR04b166HGsBa/R4U3SueirEUpXGuw+Q0=
|
||||
github.com/tklauser/go-sysconf v0.3.14 h1:g5vzr9iPFFz24v2KZXs/pvpvh8/V9Fw6vQK5ZZb78yU=
|
||||
github.com/tklauser/go-sysconf v0.3.14/go.mod h1:1ym4lWMLUOhuBOPGtRcJm7tEGX4SCYNEEEtghGG/8uY=
|
||||
github.com/tklauser/numcpus v0.8.0 h1:Mx4Wwe/FjZLeQsK/6kt2EOepwwSl7SmJrK5bV/dXYgY=
|
||||
github.com/tklauser/numcpus v0.8.0/go.mod h1:ZJZlAY+dmR4eut8epnzf0u/VwodKmryxR8txiloSqBE=
|
||||
github.com/tnb-labs/acmez/v3 v3.0.0-20241217024017-a2f2c48efdcc h1:DjqfrS/10NQOqx8yFtPcNfbAN5wrjnYgaub+ZQXPHEY=
|
||||
github.com/tnb-labs/acmez/v3 v3.0.0-20241217024017-a2f2c48efdcc/go.mod h1:L1wOU06KKvq7tswuMDwKdcHeKpFFgkppZy/y0DFxagQ=
|
||||
github.com/tufanbarisyildirim/gonginx v0.0.0-20241225173012-5cc15aab65bd h1:PYNV7LTzEzZ4lousHUM2yaDO2zI3FNt9NA0iuGrbK7w=
|
||||
github.com/tufanbarisyildirim/gonginx v0.0.0-20241225173012-5cc15aab65bd/go.mod h1:hdMWBc1+TyB6G5ZZBBgPWQ8cjRZ6zpYdhal0uu6E9QM=
|
||||
github.com/tklauser/numcpus v0.9.0 h1:lmyCHtANi8aRUgkckBgoDk1nHCux3n2cgkJLXdQGPDo=
|
||||
github.com/tklauser/numcpus v0.9.0/go.mod h1:SN6Nq1O3VychhC1npsWostA+oW+VOQTxZrS604NSRyI=
|
||||
github.com/tnb-labs/acmez/v3 v3.0.0-20250101070450-67fb7b3d86d1 h1:7IhZYEiBWy3KfKi9wZkv4Um8QYYF2fYzQ+xNrOx/tHI=
|
||||
github.com/tnb-labs/acmez/v3 v3.0.0-20250101070450-67fb7b3d86d1/go.mod h1:L1wOU06KKvq7tswuMDwKdcHeKpFFgkppZy/y0DFxagQ=
|
||||
github.com/tufanbarisyildirim/gonginx v0.0.0-20250120210832-12a9c7ae0c8a h1:bFMBmB409YhHd+B4yfM7JPYTCgxnQjqzIfFOiN4Tpsc=
|
||||
github.com/tufanbarisyildirim/gonginx v0.0.0-20250120210832-12a9c7ae0c8a/go.mod h1:hdMWBc1+TyB6G5ZZBBgPWQ8cjRZ6zpYdhal0uu6E9QM=
|
||||
github.com/urfave/cli/v3 v3.0.0-beta1 h1:6DTaaUarcM0wX7qj5Hcvs+5Dm3dyUTBbEwIWAjcw9Zg=
|
||||
github.com/urfave/cli/v3 v3.0.0-beta1/go.mod h1:FnIeEMYu+ko8zP1F9Ypr3xkZMIDqW3DR92yUtY39q1Y=
|
||||
github.com/xo/terminfo v0.0.0-20220910002029-abceb7e1c41e h1:JVG44RsyaB9T2KIHavMF/ppJZNG9ZpyihvCd0w101no=
|
||||
@@ -160,16 +159,16 @@ golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACk
|
||||
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
|
||||
golang.org/x/crypto v0.13.0/go.mod h1:y6Z2r+Rw4iayiXXAIxJIDAJ1zMW4yaTpebo8fPOliYc=
|
||||
golang.org/x/crypto v0.18.0/go.mod h1:R0j02AL6hcrfOiy9T4ZYp/rcWeMxM3L6QYxlOuEG1mg=
|
||||
golang.org/x/crypto v0.31.0 h1:ihbySMvVjLAeSH1IbfcRTkD/iNscyz8rGzjF/E5hV6U=
|
||||
golang.org/x/crypto v0.31.0/go.mod h1:kDsLvtWBEx7MV9tJOj9bnXsPbxwJQ6csT/x4KIN4Ssk=
|
||||
golang.org/x/exp v0.0.0-20240909161429-701f63a606c0 h1:e66Fs6Z+fZTbFBAxKfP3PALWBtpfqks2bwGcexMxgtk=
|
||||
golang.org/x/exp v0.0.0-20240909161429-701f63a606c0/go.mod h1:2TbTHSBQa924w8M6Xs1QcRcFwyucIwBGpK1p2f1YFFY=
|
||||
golang.org/x/crypto v0.33.0 h1:IOBPskki6Lysi0lo9qQvbxiQ+FvsCC/YWOecCHAixus=
|
||||
golang.org/x/crypto v0.33.0/go.mod h1:bVdXmD7IV/4GdElGPozy6U7lWdRXA4qyRVGJV57uQ5M=
|
||||
golang.org/x/exp v0.0.0-20250210185358-939b2ce775ac h1:l5+whBCLH3iH2ZNHYLbAe58bo7yrN4mVcnkHDYz5vvs=
|
||||
golang.org/x/exp v0.0.0-20250210185358-939b2ce775ac/go.mod h1:hH+7mtFmImwwcMvScyxUhjuVHR3HGaDPMn9rMSUUbxo=
|
||||
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
|
||||
golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
|
||||
golang.org/x/mod v0.12.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
|
||||
golang.org/x/mod v0.14.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c=
|
||||
golang.org/x/mod v0.21.0 h1:vvrHzRwRfVKSiLrG+d4FMl/Qi4ukBCE6kZlTUkDYRT0=
|
||||
golang.org/x/mod v0.21.0/go.mod h1:6SkKJ3Xj0I0BrPOZoBy3bdMptDDU9oJrpohJ3eWZ1fY=
|
||||
golang.org/x/mod v0.23.0 h1:Zb7khfcRGKk+kqfxFaP5tZqCnDZMjC5VtUBs87Hr6QM=
|
||||
golang.org/x/mod v0.23.0/go.mod h1:6SkKJ3Xj0I0BrPOZoBy3bdMptDDU9oJrpohJ3eWZ1fY=
|
||||
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
|
||||
golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
|
||||
@@ -177,36 +176,37 @@ golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs=
|
||||
golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg=
|
||||
golang.org/x/net v0.15.0/go.mod h1:idbUs1IY1+zTqbi8yxTbhexhEEk5ur9LInksu6HrEpk=
|
||||
golang.org/x/net v0.20.0/go.mod h1:z8BVo6PvndSri0LbOE3hAn0apkU+1YvI6E70E9jsnvY=
|
||||
golang.org/x/net v0.33.0 h1:74SYHlV8BIgHIFC/LrYkOGIwL19eTYXQ5wc6TBuO36I=
|
||||
golang.org/x/net v0.33.0/go.mod h1:HXLR5J+9DxmrqMwG9qjGCxZ+zKXxBru04zlTvWlWuN4=
|
||||
golang.org/x/net v0.35.0 h1:T5GQRQb2y08kTAByq9L4/bz8cipCdA8FbRTXewonqY8=
|
||||
golang.org/x/net v0.35.0/go.mod h1:EglIi67kWsHKlRzzVMUD93VMSWGFOMSZgxFjparz1Qk=
|
||||
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.3.0/go.mod h1:FU7BRWz2tNW+3quACPkgCx/L+uEAv1htQ0V83Z9Rj+Y=
|
||||
golang.org/x/sync v0.6.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
|
||||
golang.org/x/sync v0.10.0 h1:3NQrjDixjgGwUOCaF8w2+VYHv0Ve/vGYSbdkTa98gmQ=
|
||||
golang.org/x/sync v0.10.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
|
||||
golang.org/x/sync v0.11.0 h1:GGz8+XQP4FvTTrjZPzNKTMFtSXH80RAzG+5ghFPgK9w=
|
||||
golang.org/x/sync v0.11.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
|
||||
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20190916202348-b4ddaad3f8a3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.16.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||
golang.org/x/sys v0.28.0 h1:Fksou7UEQUWlKvIdsqzJmUmCX3cZuD2+P3XyyzwMhlA=
|
||||
golang.org/x/sys v0.28.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||
golang.org/x/sys v0.30.0 h1:QjkSwP/36a20jFYWkSue1YwXzLmsV5Gfq7Eiy72C1uc=
|
||||
golang.org/x/sys v0.30.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
||||
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
|
||||
golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k=
|
||||
golang.org/x/term v0.8.0/go.mod h1:xPskH00ivmX89bAKVGSKKtLOWNx2+17Eiy94tnKShWo=
|
||||
golang.org/x/term v0.12.0/go.mod h1:owVbMEjm3cBLCHdkQu9b1opXd4ETQWc3BhuQGKgXgvU=
|
||||
golang.org/x/term v0.16.0/go.mod h1:yn7UURbUtPyrVJPGPq404EukNFxcm/foM+bV/bfcDsY=
|
||||
golang.org/x/term v0.27.0 h1:WP60Sv1nlK1T6SupCHbXzSaN0b9wUmsPoRS9b61A23Q=
|
||||
golang.org/x/term v0.27.0/go.mod h1:iMsnZpn0cago0GOrHO2+Y7u7JPn5AylBrcoWkElMTSM=
|
||||
golang.org/x/term v0.29.0 h1:L6pJp37ocefwRRtYPKSWOWzOtWSxVajvz2ldH/xi3iU=
|
||||
golang.org/x/term v0.29.0/go.mod h1:6bl4lRlvVuDgSf3179VpIxBF0o10JUpXWOnI7nErv7s=
|
||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
|
||||
@@ -214,8 +214,8 @@ golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
|
||||
golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8=
|
||||
golang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE=
|
||||
golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
|
||||
golang.org/x/text v0.21.0 h1:zyQAAkrwaneQ066sspRyJaG9VNi/YJ1NfzcGB3hZ/qo=
|
||||
golang.org/x/text v0.21.0/go.mod h1:4IBbMaMmOPCJ8SecivzSH54+73PCFmPWxNTLm+vZkEQ=
|
||||
golang.org/x/text v0.22.0 h1:bofq7m3/HAFvbF51jz3Q9wLg3jkvSPuiZu/pD1XwgtM=
|
||||
golang.org/x/text v0.22.0/go.mod h1:YRoo4H8PVmsu+E3Ou7cqLVH8oXWIHVoX0jqUWALQhfY=
|
||||
golang.org/x/time v0.6.0 h1:eTDhh4ZXt5Qf0augr54TN6suAUudPcawVZeIAPU7D4U=
|
||||
golang.org/x/time v0.6.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM=
|
||||
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||
@@ -224,8 +224,8 @@ golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc
|
||||
golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU=
|
||||
golang.org/x/tools v0.13.0/go.mod h1:HvlwmtVNQAhOuCjW7xxvovg8wbNq7LwfXh/k7wXUl58=
|
||||
golang.org/x/tools v0.17.0/go.mod h1:xsh6VxdV005rRVaS6SSAf9oiAqljS7UZUacMZ8Bnsps=
|
||||
golang.org/x/tools v0.25.0 h1:oFU9pkj/iJgs+0DT+VMHrx+oBKs/LJMV+Uvg78sl+fE=
|
||||
golang.org/x/tools v0.25.0/go.mod h1:/vtpO8WL1N9cQC3FN5zPqb//fRXskFHbLKk4OW1Q7rg=
|
||||
golang.org/x/tools v0.30.0 h1:BgcpHewrV5AUp2G9MebG4XPFI1E2W41zU1SaqVA9vJY=
|
||||
golang.org/x/tools v0.30.0/go.mod h1:c347cR/OJfw5TI+GfX7RUPNMdDRRbjvYTS0jPyvsVtY=
|
||||
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f h1:BLraFXnmrev5lT+xlilqcH8XK9/i0At2xKjWk4p6zsU=
|
||||
@@ -238,27 +238,27 @@ gorm.io/gorm v1.25.12 h1:I0u8i2hWQItBq1WfE0o2+WuL9+8L21K9e2HHSTE/0f8=
|
||||
gorm.io/gorm v1.25.12/go.mod h1:xh7N7RHfYlNc5EmcI/El95gXusucDrQnHXe0+CgWcLQ=
|
||||
gotest.tools/v3 v3.5.1 h1:EENdUnS3pdur5nybKYIh2Vfgc8IUNBjxDPSjtiJcOzU=
|
||||
gotest.tools/v3 v3.5.1/go.mod h1:isy3WKz7GK6uNw/sbHzfKBLvlvXwUyV06n6brMxxopU=
|
||||
modernc.org/cc/v4 v4.21.4 h1:3Be/Rdo1fpr8GrQ7IVw9OHtplU4gWbb+wNgeoBMmGLQ=
|
||||
modernc.org/cc/v4 v4.21.4/go.mod h1:HM7VJTZbUCR3rV8EYBi9wxnJ0ZBRiGE5OeGXNA0IsLQ=
|
||||
modernc.org/ccgo/v4 v4.21.0 h1:kKPI3dF7RIag8YcToh5ZwDcVMIv6VGa0ED5cvh0LMW4=
|
||||
modernc.org/ccgo/v4 v4.21.0/go.mod h1:h6kt6H/A2+ew/3MW/p6KEoQmrq/i3pr0J/SiwiaF/g0=
|
||||
modernc.org/cc/v4 v4.24.4 h1:TFkx1s6dCkQpd6dKurBNmpo+G8Zl4Sq/ztJ+2+DEsh0=
|
||||
modernc.org/cc/v4 v4.24.4/go.mod h1:uVtb5OGqUKpoLWhqwNQo/8LwvoiEBLvZXIQ/SmO6mL0=
|
||||
modernc.org/ccgo/v4 v4.23.16 h1:Z2N+kk38b7SfySC1ZkpGLN2vthNJP1+ZzGZIlH7uBxo=
|
||||
modernc.org/ccgo/v4 v4.23.16/go.mod h1:nNma8goMTY7aQZQNTyN9AIoJfxav4nvTnvKThAeMDdo=
|
||||
modernc.org/fileutil v1.3.0 h1:gQ5SIzK3H9kdfai/5x41oQiKValumqNTDXMvKo62HvE=
|
||||
modernc.org/fileutil v1.3.0/go.mod h1:XatxS8fZi3pS8/hKG2GH/ArUogfxjpEKs3Ku3aK4JyQ=
|
||||
modernc.org/gc/v2 v2.5.0 h1:bJ9ChznK1L1mUtAQtxi0wi5AtAs5jQuw4PrPHO5pb6M=
|
||||
modernc.org/gc/v2 v2.5.0/go.mod h1:wzN5dK1AzVGoH6XOzc3YZ+ey/jPgYHLuVckd62P0GYU=
|
||||
modernc.org/libc v1.60.1 h1:at373l8IFRTkJIkAU85BIuUoBM4T1b51ds0E1ovPG2s=
|
||||
modernc.org/libc v1.60.1/go.mod h1:xJuobKuNxKH3RUatS7GjR+suWj+5c2K7bi4m/S5arOY=
|
||||
modernc.org/mathutil v1.6.0 h1:fRe9+AmYlaej+64JsEEhoWuAYBkOtQiMEU7n/XgfYi4=
|
||||
modernc.org/mathutil v1.6.0/go.mod h1:Ui5Q9q1TR2gFm0AQRqQUaBWFLAhQpCwNcuhBOSedWPo=
|
||||
modernc.org/memory v1.8.0 h1:IqGTL6eFMaDZZhEWwcREgeMXYwmW83LYW8cROZYkg+E=
|
||||
modernc.org/memory v1.8.0/go.mod h1:XPZ936zp5OMKGWPqbD3JShgd/ZoQ7899TUuQqxY+peU=
|
||||
modernc.org/opt v0.1.3 h1:3XOZf2yznlhC+ibLltsDGzABUGVx8J6pnFMS3E4dcq4=
|
||||
modernc.org/opt v0.1.3/go.mod h1:WdSiB5evDcignE70guQKxYUl14mgWtbClRi5wmkkTX0=
|
||||
modernc.org/sortutil v1.2.0 h1:jQiD3PfS2REGJNzNCMMaLSp/wdMNieTbKX920Cqdgqc=
|
||||
modernc.org/sortutil v1.2.0/go.mod h1:TKU2s7kJMf1AE84OoiGppNHJwvB753OYfNl2WRb++Ss=
|
||||
modernc.org/sqlite v1.32.0 h1:6BM4uGza7bWypsw4fdLRsLxut6bHe4c58VeqjRgST8s=
|
||||
modernc.org/sqlite v1.32.0/go.mod h1:UqoylwmTb9F+IqXERT8bW9zzOWN8qwAIcLdzeBZs4hA=
|
||||
modernc.org/strutil v1.2.0 h1:agBi9dp1I+eOnxXeiZawM8F4LawKv4NzGWSaLfyeNZA=
|
||||
modernc.org/strutil v1.2.0/go.mod h1:/mdcBmfOibveCTBxUl5B5l6W+TTH1FXPLHZE6bTosX0=
|
||||
modernc.org/gc/v2 v2.6.3 h1:aJVhcqAte49LF+mGveZ5KPlsp4tdGdAOT4sipJXADjw=
|
||||
modernc.org/gc/v2 v2.6.3/go.mod h1:YgIahr1ypgfe7chRuJi2gD7DBQiKSLMPgBQe9oIiito=
|
||||
modernc.org/libc v1.61.13 h1:3LRd6ZO1ezsFiX1y+bHd1ipyEHIJKvuprv0sLTBwLW8=
|
||||
modernc.org/libc v1.61.13/go.mod h1:8F/uJWL/3nNil0Lgt1Dpz+GgkApWh04N3el3hxJcA6E=
|
||||
modernc.org/mathutil v1.7.1 h1:GCZVGXdaN8gTqB1Mf/usp1Y/hSqgI2vAGGP4jZMCxOU=
|
||||
modernc.org/mathutil v1.7.1/go.mod h1:4p5IwJITfppl0G4sUEDtCr4DthTaT47/N3aT6MhfgJg=
|
||||
modernc.org/memory v1.8.2 h1:cL9L4bcoAObu4NkxOlKWBWtNHIsnnACGF/TbqQ6sbcI=
|
||||
modernc.org/memory v1.8.2/go.mod h1:ZbjSvMO5NQ1A2i3bWeDiVMxIorXwdClKE/0SZ+BMotU=
|
||||
modernc.org/opt v0.1.4 h1:2kNGMRiUjrp4LcaPuLY2PzUfqM/w9N23quVwhKt5Qm8=
|
||||
modernc.org/opt v0.1.4/go.mod h1:03fq9lsNfvkYSfxrfUhZCWPk1lm4cq4N+Bh//bEtgns=
|
||||
modernc.org/sortutil v1.2.1 h1:+xyoGf15mM3NMlPDnFqrteY07klSFxLElE2PVuWIJ7w=
|
||||
modernc.org/sortutil v1.2.1/go.mod h1:7ZI3a3REbai7gzCLcotuw9AC4VZVpYMjDzETGsSMqJE=
|
||||
modernc.org/sqlite v1.34.5 h1:Bb6SR13/fjp15jt70CL4f18JIN7p7dnMExd+UFnF15g=
|
||||
modernc.org/sqlite v1.34.5/go.mod h1:YLuNmX9NKs8wRNK2ko1LW1NGYcc9FkBO69JOt1AR9JE=
|
||||
modernc.org/strutil v1.2.1 h1:UneZBkQA+DX2Rp35KcM69cSsNES9ly8mQWD71HKlOA0=
|
||||
modernc.org/strutil v1.2.1/go.mod h1:EHkiggD70koQxjVdSBM3JKM7k6L0FbGE5eymy9i3B9A=
|
||||
modernc.org/token v1.1.0 h1:Xl7Ap9dKaEs5kLoOQeQmPWevfnk/DM5qcLcYlA8ys6Y=
|
||||
modernc.org/token v1.1.0/go.mod h1:UGzOrNV1mAFSEB63lOFHIpNRUVMvYTc6yu1SMY/XTDM=
|
||||
|
||||
@@ -59,7 +59,7 @@ func (s *App) SaveConfig(w http.ResponseWriter, r *http.Request) {
|
||||
|
||||
if err = systemctl.Reload("nginx"); err != nil {
|
||||
_, err = shell.Execf("nginx -t")
|
||||
service.Error(w, http.StatusInternalServerError, "重载服务失败:%v", err)
|
||||
service.Error(w, http.StatusInternalServerError, "重载服务失败: %v", err)
|
||||
return
|
||||
}
|
||||
|
||||
|
||||
@@ -3,6 +3,7 @@ package phpmyadmin
|
||||
import (
|
||||
"fmt"
|
||||
"net/http"
|
||||
"os"
|
||||
"regexp"
|
||||
"strings"
|
||||
|
||||
@@ -32,7 +33,7 @@ func (s *App) Route(r chi.Router) {
|
||||
}
|
||||
|
||||
func (s *App) Info(w http.ResponseWriter, r *http.Request) {
|
||||
files, err := io.ReadDir(fmt.Sprintf("%s/server/phpmyadmin", app.Root))
|
||||
files, err := os.ReadDir(fmt.Sprintf("%s/server/phpmyadmin", app.Root))
|
||||
if err != nil {
|
||||
service.Error(w, http.StatusInternalServerError, "找不到 phpMyAdmin 目录")
|
||||
return
|
||||
|
||||
@@ -51,13 +51,13 @@ func (s *App) UpdateConfig(w http.ResponseWriter, r *http.Request) {
|
||||
return
|
||||
}
|
||||
|
||||
if err := io.Write(fmt.Sprintf("%s/server/postgresql/data/postgresql.conf", app.Root), req.Config, 0644); err != nil {
|
||||
if err = io.Write(fmt.Sprintf("%s/server/postgresql/data/postgresql.conf", app.Root), req.Config, 0644); err != nil {
|
||||
service.Error(w, http.StatusInternalServerError, "写入PostgreSQL配置失败")
|
||||
return
|
||||
}
|
||||
|
||||
if err := systemctl.Reload("postgresql"); err != nil {
|
||||
service.Error(w, http.StatusInternalServerError, "重载服务失败")
|
||||
if err = systemctl.Reload("postgresql"); err != nil {
|
||||
service.Error(w, http.StatusInternalServerError, "重载服务失败: %v", err)
|
||||
return
|
||||
}
|
||||
|
||||
@@ -84,13 +84,13 @@ func (s *App) UpdateUserConfig(w http.ResponseWriter, r *http.Request) {
|
||||
return
|
||||
}
|
||||
|
||||
if err := io.Write(fmt.Sprintf("%s/server/postgresql/data/pg_hba.conf", app.Root), req.Config, 0644); err != nil {
|
||||
if err = io.Write(fmt.Sprintf("%s/server/postgresql/data/pg_hba.conf", app.Root), req.Config, 0644); err != nil {
|
||||
service.Error(w, http.StatusInternalServerError, "写入PostgreSQL配置失败")
|
||||
return
|
||||
}
|
||||
|
||||
if err := systemctl.Reload("postgresql"); err != nil {
|
||||
service.Error(w, http.StatusInternalServerError, "重载服务失败")
|
||||
if err = systemctl.Reload("postgresql"); err != nil {
|
||||
service.Error(w, http.StatusInternalServerError, "重载服务失败: %v", err)
|
||||
return
|
||||
}
|
||||
|
||||
|
||||
@@ -3,6 +3,7 @@ package redis
|
||||
import (
|
||||
"fmt"
|
||||
"net/http"
|
||||
"regexp"
|
||||
"strings"
|
||||
|
||||
"github.com/go-chi/chi/v5"
|
||||
@@ -38,7 +39,20 @@ func (s *App) Load(w http.ResponseWriter, r *http.Request) {
|
||||
return
|
||||
}
|
||||
|
||||
raw, err := shell.Execf("redis-cli info")
|
||||
// 检查 Redis 密码
|
||||
withPassword := ""
|
||||
config, err := io.Read(fmt.Sprintf("%s/server/redis/redis.conf", app.Root))
|
||||
if err != nil {
|
||||
service.Error(w, http.StatusInternalServerError, "%v", err)
|
||||
return
|
||||
}
|
||||
re := regexp.MustCompile(`requirepass\s+(.+)`)
|
||||
matches := re.FindStringSubmatch(config)
|
||||
if len(matches) == 2 {
|
||||
withPassword = " -a " + matches[1]
|
||||
}
|
||||
|
||||
raw, err := shell.Execf("redis-cli%s info", withPassword)
|
||||
if err != nil {
|
||||
service.Error(w, http.StatusInternalServerError, "获取 Redis 负载失败")
|
||||
return
|
||||
|
||||
@@ -3,6 +3,7 @@ package s3fs
|
||||
import (
|
||||
"encoding/json"
|
||||
"net/http"
|
||||
"os"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
@@ -70,7 +71,7 @@ func (s *App) Create(w http.ResponseWriter, r *http.Request) {
|
||||
|
||||
// 检查挂载目录是否存在且为空
|
||||
if !io.Exists(req.Path) {
|
||||
if err = io.Mkdir(req.Path, 0755); err != nil {
|
||||
if err = os.MkdirAll(req.Path, 0755); err != nil {
|
||||
service.Error(w, http.StatusUnprocessableEntity, "failed to create mount path: %v", err)
|
||||
return
|
||||
}
|
||||
|
||||
@@ -102,7 +102,7 @@ func (s *App) UpdateConfig(w http.ResponseWriter, r *http.Request) {
|
||||
}
|
||||
|
||||
if err = systemctl.Restart(s.name); err != nil {
|
||||
service.Error(w, http.StatusInternalServerError, "重启 %s 服务失败", s.name)
|
||||
service.Error(w, http.StatusInternalServerError, "重启 %s 服务失败: %v", s.name, err)
|
||||
return
|
||||
}
|
||||
|
||||
|
||||
@@ -7,7 +7,7 @@ import (
|
||||
"github.com/glebarez/sqlite"
|
||||
"github.com/go-gormigrate/gormigrate/v2"
|
||||
"github.com/knadh/koanf/v2"
|
||||
slogGorm "github.com/orandin/slog-gorm"
|
||||
sloggorm "github.com/orandin/slog-gorm"
|
||||
"gorm.io/gorm"
|
||||
|
||||
"github.com/tnb-labs/panel/internal/app"
|
||||
@@ -17,7 +17,7 @@ import (
|
||||
func NewDB(conf *koanf.Koanf, log *slog.Logger) (*gorm.DB, error) {
|
||||
// You can use any other database, like MySQL or PostgreSQL.
|
||||
return gorm.Open(sqlite.Open(filepath.Join(app.Root, "panel/storage/app.db")), &gorm.Config{
|
||||
Logger: slogGorm.New(slogGorm.WithHandler(log.Handler())),
|
||||
Logger: sloggorm.New(sloggorm.WithHandler(log.Handler())),
|
||||
SkipDefaultTransaction: true,
|
||||
DisableForeignKeyConstraintWhenMigrating: true,
|
||||
})
|
||||
|
||||
@@ -38,7 +38,7 @@ func NewHttp(conf *koanf.Koanf, r *chi.Mux) (*hlfhr.Server, error) {
|
||||
|
||||
if conf.Bool("http.tls") {
|
||||
srv.TLSConfig = &tls.Config{
|
||||
MinVersion: tls.VersionTLS13,
|
||||
MinVersion: tls.VersionTLS12,
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -12,7 +12,7 @@ func NewSession(conf *koanf.Koanf, db *gorm.DB) (*sessions.Manager, error) {
|
||||
manager, err := sessions.NewManager(&sessions.ManagerOptions{
|
||||
Key: conf.MustString("app.key"),
|
||||
Lifetime: 120,
|
||||
GcInterval: 30,
|
||||
GcInterval: 5,
|
||||
DisableDefaultDriver: true,
|
||||
})
|
||||
if err != nil {
|
||||
|
||||
+17
-9
@@ -42,7 +42,7 @@ func (r *backupRepo) List(typ biz.BackupType) ([]*types.BackupFile, error) {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
files, err := io.ReadDir(path)
|
||||
files, err := os.ReadDir(path)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -149,7 +149,7 @@ func (r *backupRepo) CutoffLog(path, target string) error {
|
||||
// prefix 目标文件前缀
|
||||
// save 保存份数
|
||||
func (r *backupRepo) ClearExpired(path, prefix string, save int) error {
|
||||
files, err := io.ReadDir(path)
|
||||
files, err := os.ReadDir(path)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -210,7 +210,7 @@ func (r *backupRepo) GetPath(typ biz.BackupType) (string, error) {
|
||||
|
||||
backupPath = filepath.Join(backupPath, string(typ))
|
||||
if !io.Exists(backupPath) {
|
||||
if err = io.Mkdir(backupPath, 0644); err != nil {
|
||||
if err = os.MkdirAll(backupPath, 0644); err != nil {
|
||||
return "", err
|
||||
}
|
||||
}
|
||||
@@ -338,7 +338,7 @@ func (r *backupRepo) createPanel(to string) error {
|
||||
|
||||
start := time.Now()
|
||||
|
||||
temp, err := io.TempDir("panel-backup")
|
||||
temp, err := os.MkdirTemp("", "panel-backup")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -418,11 +418,13 @@ func (r *backupRepo) restoreMySQL(backup, target string) error {
|
||||
return err
|
||||
}
|
||||
|
||||
clean := false
|
||||
if !strings.HasSuffix(backup, ".sql") {
|
||||
backup, err = r.autoUnCompressSQL(backup)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
clean = true
|
||||
}
|
||||
|
||||
if _, err = shell.Execf(`mysql -u root '%s' < '%s'`, target, backup); err != nil {
|
||||
@@ -431,8 +433,10 @@ func (r *backupRepo) restoreMySQL(backup, target string) error {
|
||||
if err = os.Unsetenv("MYSQL_PWD"); err != nil {
|
||||
return err
|
||||
}
|
||||
if clean {
|
||||
_ = io.Remove(filepath.Dir(backup))
|
||||
}
|
||||
|
||||
_ = io.Remove(filepath.Dir(backup))
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -451,18 +455,22 @@ func (r *backupRepo) restorePostgres(backup, target string) error {
|
||||
return fmt.Errorf("数据库不存在:%s", target)
|
||||
}
|
||||
|
||||
clean := false
|
||||
if !strings.HasSuffix(backup, ".sql") {
|
||||
backup, err = r.autoUnCompressSQL(backup)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
clean = true
|
||||
}
|
||||
|
||||
if _, err = shell.Execf(`su - postgres -c "psql '%s'" < '%s'`, target, backup); err != nil {
|
||||
return err
|
||||
}
|
||||
if clean {
|
||||
_ = io.Remove(filepath.Dir(backup))
|
||||
}
|
||||
|
||||
_ = io.Remove(filepath.Dir(backup))
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -525,7 +533,7 @@ func (r *backupRepo) preCheckDB(to string, size int64) error {
|
||||
|
||||
// autoUnCompressSQL 自动处理压缩文件
|
||||
func (r *backupRepo) autoUnCompressSQL(backup string) (string, error) {
|
||||
temp, err := io.TempDir(backup)
|
||||
temp, err := os.MkdirTemp("", "sql-uncompress")
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
@@ -674,7 +682,7 @@ func (r *backupRepo) FixPanel() error {
|
||||
if err = io.Chmod("/usr/local/etc/panel/config.yml", 0600); err != nil {
|
||||
return err
|
||||
}
|
||||
if err = io.Chmod("/etc/systemd/system/panel.service", 0700); err != nil {
|
||||
if err = io.Chmod("/etc/systemd/system/panel.service", 0644); err != nil {
|
||||
return err
|
||||
}
|
||||
if err = io.Chmod("/usr/local/sbin/panel-cli", 0700); err != nil {
|
||||
@@ -815,7 +823,7 @@ func (r *backupRepo) UpdatePanel(version, url, checksum string) error {
|
||||
fmt.Println("|-设置关键文件权限...")
|
||||
}
|
||||
_ = io.Chmod("/usr/local/sbin/panel-cli", 0700)
|
||||
_ = io.Chmod("/etc/systemd/system/panel.service", 0700)
|
||||
_ = io.Chmod("/etc/systemd/system/panel.service", 0644)
|
||||
_ = io.Chmod(filepath.Join(app.Root, "panel"), 0700)
|
||||
|
||||
if app.IsCli {
|
||||
|
||||
@@ -119,6 +119,9 @@ func (r *certRepo) Update(req *request.CertUpdate) error {
|
||||
if err == nil && req.Type == "upload" {
|
||||
req.Domains = info.DNSNames
|
||||
}
|
||||
if req.Type == "upload" && req.AutoRenew {
|
||||
return errors.New("upload certificate cannot be set to auto renew")
|
||||
}
|
||||
|
||||
return r.db.Model(&biz.Cert{}).Where("id = ?", req.ID).Select("*").Updates(&biz.Cert{
|
||||
ID: req.ID,
|
||||
|
||||
+10
-10
@@ -152,59 +152,59 @@ func (r *containerRepo) Create(req *request.ContainerCreate) (string, error) {
|
||||
|
||||
// Remove 移除容器
|
||||
func (r *containerRepo) Remove(id string) error {
|
||||
_, err := shell.ExecfWithTimeout(120*time.Second, "docker rm -f %s", id)
|
||||
_, err := shell.ExecfWithTimeout(2*time.Minute, "docker rm -f %s", id)
|
||||
return err
|
||||
}
|
||||
|
||||
// Start 启动容器
|
||||
func (r *containerRepo) Start(id string) error {
|
||||
_, err := shell.ExecfWithTimeout(120*time.Second, "docker start %s", id)
|
||||
_, err := shell.ExecfWithTimeout(2*time.Minute, "docker start %s", id)
|
||||
return err
|
||||
}
|
||||
|
||||
// Stop 停止容器
|
||||
func (r *containerRepo) Stop(id string) error {
|
||||
_, err := shell.ExecfWithTimeout(120*time.Second, "docker stop %s", id)
|
||||
_, err := shell.ExecfWithTimeout(2*time.Minute, "docker stop %s", id)
|
||||
return err
|
||||
}
|
||||
|
||||
// Restart 重启容器
|
||||
func (r *containerRepo) Restart(id string) error {
|
||||
_, err := shell.ExecfWithTimeout(120*time.Second, "docker restart %s", id)
|
||||
_, err := shell.ExecfWithTimeout(2*time.Minute, "docker restart %s", id)
|
||||
return err
|
||||
}
|
||||
|
||||
// Pause 暂停容器
|
||||
func (r *containerRepo) Pause(id string) error {
|
||||
_, err := shell.ExecfWithTimeout(120*time.Second, "docker pause %s", id)
|
||||
_, err := shell.ExecfWithTimeout(2*time.Minute, "docker pause %s", id)
|
||||
return err
|
||||
}
|
||||
|
||||
// Unpause 恢复容器
|
||||
func (r *containerRepo) Unpause(id string) error {
|
||||
_, err := shell.ExecfWithTimeout(120*time.Second, "docker unpause %s", id)
|
||||
_, err := shell.ExecfWithTimeout(2*time.Minute, "docker unpause %s", id)
|
||||
return err
|
||||
}
|
||||
|
||||
// Kill 杀死容器
|
||||
func (r *containerRepo) Kill(id string) error {
|
||||
_, err := shell.ExecfWithTimeout(120*time.Second, "docker kill %s", id)
|
||||
_, err := shell.ExecfWithTimeout(2*time.Minute, "docker kill %s", id)
|
||||
return err
|
||||
}
|
||||
|
||||
// Rename 重命名容器
|
||||
func (r *containerRepo) Rename(id string, newName string) error {
|
||||
_, err := shell.ExecfWithTimeout(120*time.Second, "docker rename %s %s", id, newName)
|
||||
_, err := shell.ExecfWithTimeout(2*time.Minute, "docker rename %s %s", id, newName)
|
||||
return err
|
||||
}
|
||||
|
||||
// Logs 查看容器日志
|
||||
func (r *containerRepo) Logs(id string) (string, error) {
|
||||
return shell.ExecfWithTimeout(120*time.Second, "docker logs %s", id)
|
||||
return shell.ExecfWithTimeout(2*time.Minute, "docker logs %s", id)
|
||||
}
|
||||
|
||||
// Prune 清理未使用的容器
|
||||
func (r *containerRepo) Prune() error {
|
||||
_, err := shell.ExecfWithTimeout(120*time.Second, "docker container prune -f")
|
||||
_, err := shell.ExecfWithTimeout(2*time.Minute, "docker container prune -f")
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -77,12 +77,12 @@ func (r *containerImageRepo) Pull(req *request.ContainerImagePull) error {
|
||||
|
||||
// Remove 删除镜像
|
||||
func (r *containerImageRepo) Remove(id string) error {
|
||||
_, err := shell.ExecfWithTimeout(120*time.Second, "docker rmi %s", id)
|
||||
_, err := shell.ExecfWithTimeout(2*time.Minute, "docker rmi %s", id)
|
||||
return err
|
||||
}
|
||||
|
||||
// Prune 清理未使用的镜像
|
||||
func (r *containerImageRepo) Prune() error {
|
||||
_, err := shell.ExecfWithTimeout(120*time.Second, "docker image prune -f")
|
||||
_, err := shell.ExecfWithTimeout(2*time.Minute, "docker image prune -f")
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -104,12 +104,12 @@ func (r *containerNetworkRepo) Create(req *request.ContainerNetworkCreate) (stri
|
||||
|
||||
// Remove 删除网络
|
||||
func (r *containerNetworkRepo) Remove(id string) error {
|
||||
_, err := shell.ExecfWithTimeout(120*time.Second, "docker network rm -f %s", id)
|
||||
_, err := shell.ExecfWithTimeout(2*time.Minute, "docker network rm -f %s", id)
|
||||
return err
|
||||
}
|
||||
|
||||
// Prune 清理未使用的网络
|
||||
func (r *containerNetworkRepo) Prune() error {
|
||||
_, err := shell.ExecfWithTimeout(120*time.Second, "docker network prune -f")
|
||||
_, err := shell.ExecfWithTimeout(2*time.Minute, "docker network prune -f")
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -78,12 +78,12 @@ func (r *containerVolumeRepo) Create(req *request.ContainerVolumeCreate) (string
|
||||
|
||||
// Remove 删除存储卷
|
||||
func (r *containerVolumeRepo) Remove(id string) error {
|
||||
_, err := shell.ExecfWithTimeout(120*time.Second, "docker volume rm -f %s", id)
|
||||
_, err := shell.ExecfWithTimeout(2*time.Minute, "docker volume rm -f %s", id)
|
||||
return err
|
||||
}
|
||||
|
||||
// Prune 清理未使用的存储卷
|
||||
func (r *containerVolumeRepo) Prune() error {
|
||||
_, err := shell.ExecfWithTimeout(120*time.Second, "docker volume prune -f")
|
||||
_, err := shell.ExecfWithTimeout(2*time.Minute, "docker volume prune -f")
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -85,8 +85,8 @@ export PATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin:$PATH
|
||||
# 耗子面板 - 日志切割脚本
|
||||
|
||||
# 执行切割
|
||||
panel-cli cutoff website -n %s -p %s
|
||||
panel-cli cutoff clear -t website -f %s -s %d -p %s
|
||||
panel-cli cutoff website -n '%s' -p '%s'
|
||||
panel-cli cutoff clear -t website -f '%s' -s '%d' -p '%s'
|
||||
`, req.Target, req.BackupPath, req.Target, req.Save, req.BackupPath)
|
||||
}
|
||||
if req.Type == "shell" {
|
||||
|
||||
@@ -5,6 +5,7 @@ import (
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"slices"
|
||||
"strings"
|
||||
@@ -185,7 +186,13 @@ func (r *websiteRepo) Get(id uint) (*types.WebsiteSetting, error) {
|
||||
rewrite, _ := io.Read(filepath.Join(app.Root, "server/vhost/rewrite", website.Name+".conf"))
|
||||
setting.Rewrite = rewrite
|
||||
// 访问日志
|
||||
setting.Log = fmt.Sprintf("%s/wwwlogs/%s.log", app.Root, website.Name)
|
||||
if setting.Log, err = p.GetAccessLog(); err != nil {
|
||||
setting.Log = fmt.Sprintf("%s/wwwlogs/%s.log", app.Root, website.Name)
|
||||
}
|
||||
// 错误日志
|
||||
if setting.ErrorLog, err = p.GetErrorLog(); err != nil {
|
||||
setting.ErrorLog = fmt.Sprintf("%s/wwwlogs/%s.error.log", app.Root, website.Name)
|
||||
}
|
||||
|
||||
return setting, err
|
||||
}
|
||||
@@ -266,7 +273,7 @@ func (r *websiteRepo) Create(req *request.WebsiteCreate) (*biz.Website, error) {
|
||||
}
|
||||
|
||||
// 初始化网站目录
|
||||
if err = io.Mkdir(req.Path, 0755); err != nil {
|
||||
if err = os.MkdirAll(req.Path, 0755); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
index, err := embed.WebsiteFS.ReadFile(filepath.Join("website", "index.html"))
|
||||
|
||||
@@ -13,11 +13,11 @@ import (
|
||||
// 例子:exists:users,phone,email
|
||||
// Example: exists:users,phone,email
|
||||
type Exists struct {
|
||||
DB *gorm.DB
|
||||
db *gorm.DB
|
||||
}
|
||||
|
||||
func NewExists(db *gorm.DB) *Exists {
|
||||
return &Exists{DB: db}
|
||||
return &Exists{db: db}
|
||||
}
|
||||
|
||||
func (r *Exists) Passes(val any, options ...any) bool {
|
||||
@@ -28,7 +28,7 @@ func (r *Exists) Passes(val any, options ...any) bool {
|
||||
tableName := options[0].(string)
|
||||
fieldNames := options[1:]
|
||||
|
||||
query := r.DB.Table(tableName).Where(fmt.Sprintf("%s = ?", fieldNames[0]), val)
|
||||
query := r.db.Table(tableName).Where(fmt.Sprintf("%s = ?", fieldNames[0]), val)
|
||||
for _, fieldName := range fieldNames[1:] {
|
||||
query = query.Or(fmt.Sprintf("%s = ?", fieldName), val)
|
||||
}
|
||||
|
||||
@@ -13,11 +13,11 @@ import (
|
||||
// 例子:notExists:users,phone,email
|
||||
// Example: notExists:users,phone,email
|
||||
type NotExists struct {
|
||||
DB *gorm.DB
|
||||
db *gorm.DB
|
||||
}
|
||||
|
||||
func NewNotExists(db *gorm.DB) *NotExists {
|
||||
return &NotExists{DB: db}
|
||||
return &NotExists{db: db}
|
||||
}
|
||||
|
||||
func (r *NotExists) Passes(val any, options ...any) bool {
|
||||
@@ -28,7 +28,7 @@ func (r *NotExists) Passes(val any, options ...any) bool {
|
||||
tableName := options[0].(string)
|
||||
fieldNames := options[1:]
|
||||
|
||||
query := r.DB.Table(tableName).Where(fmt.Sprintf("%s = ?", fieldNames[0]), val)
|
||||
query := r.db.Table(tableName).Where(fmt.Sprintf("%s = ?", fieldNames[0]), val)
|
||||
for _, fieldName := range fieldNames[1:] {
|
||||
query = query.Or(fmt.Sprintf("%s = ?", fieldName), val)
|
||||
}
|
||||
|
||||
+4
-2
@@ -19,9 +19,10 @@ type Jobs struct {
|
||||
cert biz.CertRepo
|
||||
backup biz.BackupRepo
|
||||
cache biz.CacheRepo
|
||||
task biz.TaskRepo
|
||||
}
|
||||
|
||||
func NewJobs(db *gorm.DB, log *slog.Logger, setting biz.SettingRepo, cert biz.CertRepo, backup biz.BackupRepo, cache biz.CacheRepo) *Jobs {
|
||||
func NewJobs(db *gorm.DB, log *slog.Logger, setting biz.SettingRepo, cert biz.CertRepo, backup biz.BackupRepo, cache biz.CacheRepo, task biz.TaskRepo) *Jobs {
|
||||
return &Jobs{
|
||||
db: db,
|
||||
log: log,
|
||||
@@ -29,6 +30,7 @@ func NewJobs(db *gorm.DB, log *slog.Logger, setting biz.SettingRepo, cert biz.Ce
|
||||
cert: cert,
|
||||
backup: backup,
|
||||
cache: cache,
|
||||
task: task,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -40,7 +42,7 @@ func (r *Jobs) Register(c *cron.Cron) error {
|
||||
return err
|
||||
}
|
||||
|
||||
if _, err := c.AddJob("0 2 * * *", NewPanelTask(r.db, r.log, r.backup, r.cache, r.setting)); err != nil {
|
||||
if _, err := c.AddJob("0 2 * * *", NewPanelTask(r.db, r.log, r.backup, r.cache, r.task, r.setting)); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
|
||||
@@ -23,16 +23,18 @@ type PanelTask struct {
|
||||
log *slog.Logger
|
||||
backupRepo biz.BackupRepo
|
||||
cacheRepo biz.CacheRepo
|
||||
taskRepo biz.TaskRepo
|
||||
settingRepo biz.SettingRepo
|
||||
}
|
||||
|
||||
func NewPanelTask(db *gorm.DB, log *slog.Logger, backup biz.BackupRepo, cache biz.CacheRepo, setting biz.SettingRepo) *PanelTask {
|
||||
func NewPanelTask(db *gorm.DB, log *slog.Logger, backup biz.BackupRepo, cache biz.CacheRepo, task biz.TaskRepo, setting biz.SettingRepo) *PanelTask {
|
||||
return &PanelTask{
|
||||
api: api.NewAPI(app.Version),
|
||||
db: db,
|
||||
log: log,
|
||||
backupRepo: backup,
|
||||
cacheRepo: cache,
|
||||
taskRepo: task,
|
||||
settingRepo: setting,
|
||||
}
|
||||
}
|
||||
@@ -100,6 +102,10 @@ func (r *PanelTask) updateRewrites() {
|
||||
|
||||
// 更新面板
|
||||
func (r *PanelTask) updatePanel() {
|
||||
if r.taskRepo.HasRunningTask() {
|
||||
return
|
||||
}
|
||||
|
||||
// 加 300 秒确保在缓存更新后才更新面板
|
||||
time.AfterFunc(time.Duration(rand.IntN(300))*time.Second+300*time.Second, func() {
|
||||
panel, err := r.api.LatestVersion()
|
||||
|
||||
@@ -72,7 +72,7 @@ func (s *BackupService) Upload(w http.ResponseWriter, r *http.Request) {
|
||||
}
|
||||
|
||||
if !io.Exists(filepath.Dir(path)) {
|
||||
if err = io.Mkdir(filepath.Dir(path), 0755); err != nil {
|
||||
if err = os.MkdirAll(filepath.Dir(path), 0755); err != nil {
|
||||
Error(w, http.StatusInternalServerError, "创建文件夹失败:%v", err)
|
||||
return
|
||||
}
|
||||
|
||||
@@ -51,7 +51,7 @@ func (s *FileService) Create(w http.ResponseWriter, r *http.Request) {
|
||||
return
|
||||
}
|
||||
} else {
|
||||
if err = io.Mkdir(req.Path, 0755); err != nil {
|
||||
if err = stdos.MkdirAll(req.Path, 0755); err != nil {
|
||||
Error(w, http.StatusInternalServerError, "%v", err)
|
||||
return
|
||||
}
|
||||
@@ -159,7 +159,7 @@ func (s *FileService) Upload(w http.ResponseWriter, r *http.Request) {
|
||||
}
|
||||
|
||||
if !io.Exists(filepath.Dir(path)) {
|
||||
if err = io.Mkdir(filepath.Dir(path), 0755); err != nil {
|
||||
if err = stdos.MkdirAll(filepath.Dir(path), 0755); err != nil {
|
||||
Error(w, http.StatusInternalServerError, "create directory error: %v", err)
|
||||
return
|
||||
}
|
||||
@@ -291,7 +291,7 @@ func (s *FileService) RemoteDownload(w http.ResponseWriter, r *http.Request) {
|
||||
task := new(biz.Task)
|
||||
task.Name = "下载远程文件"
|
||||
task.Status = biz.TaskStatusWaiting
|
||||
task.Shell = fmt.Sprintf(`wget -o /tmp/remote-download-%s.log -O '%s' '%s'`, timestamp, req.Path, req.URL)
|
||||
task.Shell = fmt.Sprintf(`wget -o /tmp/remote-download-%s.log -O '%s' '%s' && chmod 0755 '%s' && chown www:www '%s'`, timestamp, req.Path, req.URL, req.Path, req.Path)
|
||||
task.Log = fmt.Sprintf("/tmp/remote-download-%s.log", timestamp)
|
||||
|
||||
if err = s.taskRepo.Push(task); err != nil {
|
||||
@@ -420,7 +420,7 @@ func (s *FileService) List(w http.ResponseWriter, r *http.Request) {
|
||||
return
|
||||
}
|
||||
|
||||
list, err := io.ReadDir(req.Path)
|
||||
list, err := stdos.ReadDir(req.Path)
|
||||
if err != nil {
|
||||
Error(w, http.StatusInternalServerError, "%v", err)
|
||||
return
|
||||
|
||||
@@ -23,7 +23,7 @@ func (s *SystemctlService) Status(w http.ResponseWriter, r *http.Request) {
|
||||
|
||||
status, err := systemctl.Status(req.Service)
|
||||
if err != nil {
|
||||
Error(w, http.StatusInternalServerError, "获取 %s 服务运行状态失败", req.Service)
|
||||
Error(w, http.StatusInternalServerError, "获取 %s 服务运行状态失败: %v", req.Service, err)
|
||||
return
|
||||
}
|
||||
|
||||
@@ -39,7 +39,7 @@ func (s *SystemctlService) IsEnabled(w http.ResponseWriter, r *http.Request) {
|
||||
|
||||
enabled, err := systemctl.IsEnabled(req.Service)
|
||||
if err != nil {
|
||||
Error(w, http.StatusInternalServerError, "获取 %s 服务启用状态失败", req.Service)
|
||||
Error(w, http.StatusInternalServerError, "获取 %s 服务启用状态失败: %v", req.Service, err)
|
||||
return
|
||||
}
|
||||
|
||||
@@ -54,7 +54,7 @@ func (s *SystemctlService) Enable(w http.ResponseWriter, r *http.Request) {
|
||||
}
|
||||
|
||||
if err = systemctl.Enable(req.Service); err != nil {
|
||||
Error(w, http.StatusInternalServerError, "启用 %s 服务失败", req.Service)
|
||||
Error(w, http.StatusInternalServerError, "启用 %s 服务失败: %v", req.Service, err)
|
||||
return
|
||||
}
|
||||
|
||||
@@ -69,7 +69,7 @@ func (s *SystemctlService) Disable(w http.ResponseWriter, r *http.Request) {
|
||||
}
|
||||
|
||||
if err = systemctl.Disable(req.Service); err != nil {
|
||||
Error(w, http.StatusInternalServerError, "禁用 %s 服务失败", req.Service)
|
||||
Error(w, http.StatusInternalServerError, "禁用 %s 服务失败: %v", req.Service, err)
|
||||
return
|
||||
}
|
||||
|
||||
@@ -84,7 +84,7 @@ func (s *SystemctlService) Restart(w http.ResponseWriter, r *http.Request) {
|
||||
}
|
||||
|
||||
if err = systemctl.Restart(req.Service); err != nil {
|
||||
Error(w, http.StatusInternalServerError, "重启 %s 服务失败", req.Service)
|
||||
Error(w, http.StatusInternalServerError, "重启 %s 服务失败: %v", req.Service, err)
|
||||
return
|
||||
}
|
||||
|
||||
@@ -99,7 +99,7 @@ func (s *SystemctlService) Reload(w http.ResponseWriter, r *http.Request) {
|
||||
}
|
||||
|
||||
if err = systemctl.Reload(req.Service); err != nil {
|
||||
Error(w, http.StatusInternalServerError, "重载 %s 服务失败", req.Service)
|
||||
Error(w, http.StatusInternalServerError, "重载 %s 服务失败: %v", req.Service, err)
|
||||
return
|
||||
}
|
||||
|
||||
@@ -114,7 +114,7 @@ func (s *SystemctlService) Start(w http.ResponseWriter, r *http.Request) {
|
||||
}
|
||||
|
||||
if err = systemctl.Start(req.Service); err != nil {
|
||||
Error(w, http.StatusInternalServerError, "启动 %s 服务失败", req.Service)
|
||||
Error(w, http.StatusInternalServerError, "启动 %s 服务失败: %v", req.Service, err)
|
||||
return
|
||||
}
|
||||
|
||||
@@ -129,7 +129,7 @@ func (s *SystemctlService) Stop(w http.ResponseWriter, r *http.Request) {
|
||||
}
|
||||
|
||||
if err = systemctl.Stop(req.Service); err != nil {
|
||||
Error(w, http.StatusInternalServerError, "停止 %s 服务失败", req.Service)
|
||||
Error(w, http.StatusInternalServerError, "停止 %s 服务失败: %v", req.Service, err)
|
||||
return
|
||||
}
|
||||
|
||||
|
||||
@@ -93,7 +93,7 @@ func (s *WsService) Exec(w http.ResponseWriter, r *http.Request) {
|
||||
}
|
||||
|
||||
ctx, cancel := context.WithCancel(context.Background())
|
||||
out, err := shell.ExecfWithPipe(ctx, string(cmd)) // nolint: govet
|
||||
out, err := shell.ExecfWithPipe(ctx, string(cmd))
|
||||
if err != nil {
|
||||
_ = ws.WriteMessage(websocket.CloseMessage, websocket.FormatCloseMessage(websocket.CloseNormalClosure, "failed to run command"))
|
||||
cancel()
|
||||
|
||||
+9
-4
@@ -2,6 +2,7 @@ package io
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
|
||||
@@ -59,7 +60,7 @@ func UnCompress(src string, dst string) error {
|
||||
return errors.New("src and dst must be absolute path")
|
||||
}
|
||||
if !Exists(dst) {
|
||||
if err := Mkdir(dst, 0755); err != nil {
|
||||
if err := os.MkdirAll(dst, 0755); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
@@ -123,13 +124,17 @@ func formatArchiveByPath(path string) (FormatArchive, error) {
|
||||
return Bz2, nil
|
||||
case ".tar":
|
||||
return Tar, nil
|
||||
case ".gz", ".tar.gz", ".tgz":
|
||||
case ".tgz":
|
||||
return TGz, nil
|
||||
case ".gz":
|
||||
if strings.HasSuffix(path, ".tar.gz") {
|
||||
return TGz, nil
|
||||
}
|
||||
case ".xz":
|
||||
return Xz, nil
|
||||
case ".7z":
|
||||
return SevenZip, nil
|
||||
default:
|
||||
return "", errors.New("unknown format")
|
||||
}
|
||||
|
||||
return "", errors.New("unknown format")
|
||||
}
|
||||
|
||||
+4
-45
@@ -67,8 +67,6 @@ func (s *IOTestSuite) TestCompress() {
|
||||
s.NoError(err)
|
||||
err = Compress(abs, src, filepath.Join(abs, "compress_test.tar"))
|
||||
s.NoError(err)
|
||||
err = Compress(abs, src, filepath.Join(abs, "compress_test.gz"))
|
||||
s.NoError(err)
|
||||
err = Compress(abs, src, filepath.Join(abs, "compress_test.tar.gz"))
|
||||
s.NoError(err)
|
||||
err = Compress(abs, src, filepath.Join(abs, "compress_test.tgz"))
|
||||
@@ -96,8 +94,6 @@ func (s *IOTestSuite) TestUnCompress() {
|
||||
s.NoError(err)
|
||||
err = Compress(abs, src, filepath.Join(abs, "uncompress_test.tar"))
|
||||
s.NoError(err)
|
||||
err = Compress(abs, src, filepath.Join(abs, "uncompress_test.gz"))
|
||||
s.NoError(err)
|
||||
err = Compress(abs, src, filepath.Join(abs, "uncompress_test.tar.gz"))
|
||||
s.NoError(err)
|
||||
err = Compress(abs, src, filepath.Join(abs, "uncompress_test.tgz"))
|
||||
@@ -131,14 +127,6 @@ func (s *IOTestSuite) TestUnCompress() {
|
||||
data, err = Read("testdata/uncompressed_tar/uncompress_test2.txt")
|
||||
s.NoError(err)
|
||||
s.Equal("File 2", data)
|
||||
err = UnCompress(filepath.Join(abs, "uncompress_test.gz"), filepath.Join(abs, "uncompressed_gz"))
|
||||
s.NoError(err)
|
||||
data, err = Read("testdata/uncompressed_gz/uncompress_test1.txt")
|
||||
s.NoError(err)
|
||||
s.Equal("File 1", data)
|
||||
data, err = Read("testdata/uncompressed_gz/uncompress_test2.txt")
|
||||
s.NoError(err)
|
||||
s.Equal("File 2", data)
|
||||
err = UnCompress(filepath.Join(abs, "uncompress_test.tar.gz"), filepath.Join(abs, "uncompressed_tar_gz"))
|
||||
s.NoError(err)
|
||||
data, err = Read("testdata/uncompressed_tar_gz/uncompress_test1.txt")
|
||||
@@ -190,8 +178,6 @@ func (s *IOTestSuite) TestListCompress() {
|
||||
s.NoError(err)
|
||||
err = Compress(abs, src, filepath.Join(abs, "list_archive_test.tar"))
|
||||
s.NoError(err)
|
||||
err = Compress(abs, src, filepath.Join(abs, "list_archive_test.gz"))
|
||||
s.NoError(err)
|
||||
err = Compress(abs, src, filepath.Join(abs, "list_archive_test.tar.gz"))
|
||||
s.NoError(err)
|
||||
err = Compress(abs, src, filepath.Join(abs, "list_archive_test.tgz"))
|
||||
@@ -210,9 +196,6 @@ func (s *IOTestSuite) TestListCompress() {
|
||||
list, err = ListCompress(filepath.Join(abs, "list_archive_test.tar"))
|
||||
s.NoError(err)
|
||||
s.Len(list, 2)
|
||||
list, err = ListCompress(filepath.Join(abs, "list_archive_test.gz"))
|
||||
s.NoError(err)
|
||||
s.Len(list, 2)
|
||||
list, err = ListCompress(filepath.Join(abs, "list_archive_test.tar.gz"))
|
||||
s.NoError(err)
|
||||
s.Len(list, 2)
|
||||
@@ -231,19 +214,13 @@ func (s *IOTestSuite) TestListCompress() {
|
||||
|
||||
func (s *IOTestSuite) TestRemoveDeletesFileOrDirectory() {
|
||||
path := "testdata/remove_test"
|
||||
s.NoError(Mkdir(path, 0755))
|
||||
s.NoError(os.MkdirAll(path, 0755))
|
||||
s.DirExists(path)
|
||||
|
||||
s.NoError(Remove(path))
|
||||
s.NoDirExists(path)
|
||||
}
|
||||
|
||||
func (s *IOTestSuite) TestMkdirCreatesDirectory() {
|
||||
path := "testdata/mkdir_test"
|
||||
s.NoError(Mkdir(path, 0755))
|
||||
s.DirExists(path)
|
||||
}
|
||||
|
||||
func (s *IOTestSuite) TestChmodChangesPermissions() {
|
||||
if env.IsWindows() {
|
||||
s.T().Skip("Skipping on Windows")
|
||||
@@ -280,13 +257,13 @@ func (s *IOTestSuite) TestExistsReturnsFalseForNonExistingPath() {
|
||||
|
||||
func (s *IOTestSuite) TestEmptyReturnsTrueForEmptyDirectory() {
|
||||
path := "testdata/empty_test"
|
||||
s.NoError(Mkdir(path, 0755))
|
||||
s.NoError(os.MkdirAll(path, 0755))
|
||||
s.True(Empty(path))
|
||||
}
|
||||
|
||||
func (s *IOTestSuite) TestEmptyReturnsFalseForNonEmptyDirectory() {
|
||||
path := "testdata/nonempty_test"
|
||||
s.NoError(Mkdir(path, 0755))
|
||||
s.NoError(os.MkdirAll(path, 0755))
|
||||
s.NoError(Write(filepath.Join(path, "file.txt"), "test", 0644))
|
||||
s.False(Empty(path))
|
||||
}
|
||||
@@ -321,27 +298,9 @@ func (s *IOTestSuite) TestSizeReturnsCorrectSize() {
|
||||
s.Equal(int64(len(data)), size)
|
||||
}
|
||||
|
||||
func (s *IOTestSuite) TestTempDirCreatesTemporaryDirectory() {
|
||||
dir, err := TempDir("tempdir_test")
|
||||
s.NoError(err)
|
||||
s.DirExists(dir)
|
||||
s.NoError(Remove(dir))
|
||||
}
|
||||
|
||||
func (s *IOTestSuite) TestReadDirReturnsDirectoryEntries() {
|
||||
path := "testdata/readdir_test"
|
||||
s.NoError(Mkdir(path, 0755))
|
||||
s.NoError(Write(filepath.Join(path, "file1.txt"), "test", 0644))
|
||||
s.NoError(Write(filepath.Join(path, "file2.txt"), "test", 0644))
|
||||
|
||||
entries, err := ReadDir(path)
|
||||
s.NoError(err)
|
||||
s.Len(entries, 2)
|
||||
}
|
||||
|
||||
func (s *IOTestSuite) TestIsDirReturnsTrueForDirectory() {
|
||||
path := "testdata/isdir_test"
|
||||
s.NoError(Mkdir(path, 0755))
|
||||
s.NoError(os.MkdirAll(path, 0755))
|
||||
s.True(IsDir(path))
|
||||
}
|
||||
|
||||
|
||||
@@ -16,11 +16,6 @@ func Remove(path string) error {
|
||||
return os.RemoveAll(path)
|
||||
}
|
||||
|
||||
// Mkdir 创建目录
|
||||
func Mkdir(path string, permission os.FileMode) error {
|
||||
return os.MkdirAll(path, permission)
|
||||
}
|
||||
|
||||
// Chmod 修改文件/目录权限
|
||||
func Chmod(path string, permission os.FileMode) error {
|
||||
_, err := shell.Execf("chmod -R '%o' '%s'", permission, path)
|
||||
@@ -75,16 +70,6 @@ func Size(path string) (int64, error) {
|
||||
return size, err
|
||||
}
|
||||
|
||||
// TempDir 创建临时目录
|
||||
func TempDir(prefix string) (string, error) {
|
||||
return os.MkdirTemp("", prefix)
|
||||
}
|
||||
|
||||
// ReadDir 读取目录
|
||||
func ReadDir(path string) ([]os.DirEntry, error) {
|
||||
return os.ReadDir(path)
|
||||
}
|
||||
|
||||
// IsDir 判断是否为目录
|
||||
func IsDir(path string) bool {
|
||||
info, err := os.Stat(path)
|
||||
|
||||
+37
-16
@@ -37,16 +37,19 @@ func Execf(shell string, args ...any) (string, error) {
|
||||
if !preCheckArg(args) {
|
||||
return "", errors.New("command contains illegal characters")
|
||||
}
|
||||
if len(args) > 0 {
|
||||
shell = fmt.Sprintf(shell, args...)
|
||||
}
|
||||
|
||||
_ = os.Setenv("LC_ALL", "C")
|
||||
cmd := exec.Command("bash", "-c", fmt.Sprintf(shell, args...))
|
||||
cmd := exec.Command("bash", "-c", shell)
|
||||
|
||||
var stdout, stderr bytes.Buffer
|
||||
cmd.Stdout = &stdout
|
||||
cmd.Stderr = &stderr
|
||||
|
||||
if err := cmd.Run(); err != nil {
|
||||
return strings.TrimSpace(stdout.String()), fmt.Errorf("run %s failed, err: %s", fmt.Sprintf(shell, args...), strings.TrimSpace(stderr.String()))
|
||||
return strings.TrimSpace(stdout.String()), fmt.Errorf("run %s failed, err: %s", shell, strings.TrimSpace(stderr.String()))
|
||||
}
|
||||
|
||||
return strings.TrimSpace(stdout.String()), nil
|
||||
@@ -57,9 +60,12 @@ func ExecfAsync(shell string, args ...any) error {
|
||||
if !preCheckArg(args) {
|
||||
return errors.New("command contains illegal characters")
|
||||
}
|
||||
if len(args) > 0 {
|
||||
shell = fmt.Sprintf(shell, args...)
|
||||
}
|
||||
|
||||
_ = os.Setenv("LC_ALL", "C")
|
||||
cmd := exec.Command("bash", "-c", fmt.Sprintf(shell, args...))
|
||||
cmd := exec.Command("bash", "-c", shell)
|
||||
|
||||
err := cmd.Start()
|
||||
if err != nil {
|
||||
@@ -68,7 +74,7 @@ func ExecfAsync(shell string, args ...any) error {
|
||||
|
||||
go func() {
|
||||
if err = cmd.Wait(); err != nil {
|
||||
fmt.Println(fmt.Errorf("run %s failed, err: %s", fmt.Sprintf(shell, args...), strings.TrimSpace(err.Error())))
|
||||
fmt.Println(fmt.Errorf("run %s failed, err: %s", shell, strings.TrimSpace(err.Error())))
|
||||
}
|
||||
}()
|
||||
|
||||
@@ -80,9 +86,12 @@ func ExecfWithTimeout(timeout time.Duration, shell string, args ...any) (string,
|
||||
if !preCheckArg(args) {
|
||||
return "", errors.New("command contains illegal characters")
|
||||
}
|
||||
if len(args) > 0 {
|
||||
shell = fmt.Sprintf(shell, args...)
|
||||
}
|
||||
|
||||
_ = os.Setenv("LC_ALL", "C")
|
||||
cmd := exec.Command("bash", "-c", fmt.Sprintf(shell, args...))
|
||||
cmd := exec.Command("bash", "-c", shell)
|
||||
|
||||
var stdout, stderr bytes.Buffer
|
||||
cmd.Stdout = &stdout
|
||||
@@ -90,7 +99,7 @@ func ExecfWithTimeout(timeout time.Duration, shell string, args ...any) (string,
|
||||
|
||||
err := cmd.Start()
|
||||
if err != nil {
|
||||
return strings.TrimSpace(stdout.String()), fmt.Errorf("run %s failed, err: %s", fmt.Sprintf(shell, args...), strings.TrimSpace(stderr.String()))
|
||||
return strings.TrimSpace(stdout.String()), fmt.Errorf("run %s failed, err: %s", shell, strings.TrimSpace(stderr.String()))
|
||||
}
|
||||
|
||||
done := make(chan error)
|
||||
@@ -101,10 +110,10 @@ func ExecfWithTimeout(timeout time.Duration, shell string, args ...any) (string,
|
||||
select {
|
||||
case <-time.After(timeout):
|
||||
_ = cmd.Process.Kill()
|
||||
return strings.TrimSpace(stdout.String()), fmt.Errorf("run %s failed, err: %s", fmt.Sprintf(shell, args...), "timeout")
|
||||
return strings.TrimSpace(stdout.String()), fmt.Errorf("run %s failed, err: %s", shell, "timeout")
|
||||
case err = <-done:
|
||||
if err != nil {
|
||||
return strings.TrimSpace(stdout.String()), fmt.Errorf("run %s failed, err: %s", fmt.Sprintf(shell, args...), strings.TrimSpace(stderr.String()))
|
||||
return strings.TrimSpace(stdout.String()), fmt.Errorf("run %s failed, err: %s", shell, strings.TrimSpace(stderr.String()))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -116,9 +125,12 @@ func ExecfWithOutput(shell string, args ...any) error {
|
||||
if !preCheckArg(args) {
|
||||
return errors.New("command contains illegal characters")
|
||||
}
|
||||
if len(args) > 0 {
|
||||
shell = fmt.Sprintf(shell, args...)
|
||||
}
|
||||
|
||||
_ = os.Setenv("LC_ALL", "C")
|
||||
cmd := exec.Command("bash", "-c", fmt.Sprintf(shell, args...))
|
||||
cmd := exec.Command("bash", "-c", shell)
|
||||
cmd.Stdout = os.Stdout
|
||||
cmd.Stderr = os.Stderr
|
||||
|
||||
@@ -130,9 +142,12 @@ func ExecfWithPipe(ctx context.Context, shell string, args ...any) (out io.ReadC
|
||||
if !preCheckArg(args) {
|
||||
return nil, errors.New("command contains illegal characters")
|
||||
}
|
||||
if len(args) > 0 {
|
||||
shell = fmt.Sprintf(shell, args...)
|
||||
}
|
||||
|
||||
_ = os.Setenv("LC_ALL", "C")
|
||||
cmd := exec.CommandContext(ctx, "bash", "-c", fmt.Sprintf(shell, args...))
|
||||
cmd := exec.CommandContext(ctx, "bash", "-c", shell)
|
||||
|
||||
out, err = cmd.StdoutPipe()
|
||||
if err != nil {
|
||||
@@ -149,9 +164,12 @@ func ExecfWithDir(dir, shell string, args ...any) (string, error) {
|
||||
if !preCheckArg(args) {
|
||||
return "", errors.New("command contains illegal characters")
|
||||
}
|
||||
if len(args) > 0 {
|
||||
shell = fmt.Sprintf(shell, args...)
|
||||
}
|
||||
|
||||
_ = os.Setenv("LC_ALL", "C")
|
||||
cmd := exec.Command("bash", "-c", fmt.Sprintf(shell, args...))
|
||||
cmd := exec.Command("bash", "-c", shell)
|
||||
cmd.Dir = dir
|
||||
|
||||
var stdout, stderr bytes.Buffer
|
||||
@@ -159,7 +177,7 @@ func ExecfWithDir(dir, shell string, args ...any) (string, error) {
|
||||
cmd.Stderr = &stderr
|
||||
|
||||
if err := cmd.Run(); err != nil {
|
||||
return strings.TrimSpace(stdout.String()), fmt.Errorf("run %s failed, err: %s", fmt.Sprintf(shell, args...), strings.TrimSpace(stderr.String()))
|
||||
return strings.TrimSpace(stdout.String()), fmt.Errorf("run %s failed, err: %s", shell, strings.TrimSpace(stderr.String()))
|
||||
}
|
||||
|
||||
return strings.TrimSpace(stdout.String()), nil
|
||||
@@ -170,9 +188,12 @@ func ExecfWithTTY(shell string, args ...any) (string, error) {
|
||||
if !preCheckArg(args) {
|
||||
return "", errors.New("command contains illegal characters")
|
||||
}
|
||||
if len(args) > 0 {
|
||||
shell = fmt.Sprintf(shell, args...)
|
||||
}
|
||||
|
||||
_ = os.Setenv("LC_ALL", "C")
|
||||
cmd := exec.Command("bash", "-i", "-c", fmt.Sprintf(shell, args...))
|
||||
cmd := exec.Command("bash", "-i", "-c", shell)
|
||||
|
||||
var out bytes.Buffer
|
||||
var stderr bytes.Buffer
|
||||
@@ -180,15 +201,15 @@ func ExecfWithTTY(shell string, args ...any) (string, error) {
|
||||
|
||||
f, err := pty.Start(cmd)
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("run %s failed", fmt.Sprintf(shell, args...))
|
||||
return "", fmt.Errorf("run %s failed", shell)
|
||||
}
|
||||
defer f.Close()
|
||||
|
||||
if _, err = io.Copy(&out, f); ptyError(err) != nil {
|
||||
return "", fmt.Errorf("run %s failed, out: %s, err: %w", fmt.Sprintf(shell, args...), strings.TrimSpace(out.String()), err)
|
||||
return "", fmt.Errorf("run %s failed, out: %s, err: %w", shell, strings.TrimSpace(out.String()), err)
|
||||
}
|
||||
if stderr.Len() > 0 {
|
||||
return "", fmt.Errorf("run %s failed, out: %s", fmt.Sprintf(shell, args...), strings.TrimSpace(stderr.String()))
|
||||
return "", fmt.Errorf("run %s failed, out: %s", shell, strings.TrimSpace(stderr.String()))
|
||||
}
|
||||
|
||||
return strings.TrimSpace(out.String()), nil
|
||||
|
||||
@@ -3,6 +3,7 @@ package systemctl
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
"github.com/tnb-labs/panel/pkg/shell"
|
||||
)
|
||||
@@ -38,48 +39,48 @@ func IsEnabled(name string) (bool, error) {
|
||||
|
||||
// Start 启动服务
|
||||
func Start(name string) error {
|
||||
_, err := shell.Execf("systemctl start %s", name)
|
||||
_, err := shell.ExecfWithTimeout(2*time.Minute, "systemctl start %s", name)
|
||||
return err
|
||||
}
|
||||
|
||||
// Stop 停止服务
|
||||
func Stop(name string) error {
|
||||
_, err := shell.Execf("systemctl stop %s", name)
|
||||
_, err := shell.ExecfWithTimeout(2*time.Minute, "systemctl stop %s", name)
|
||||
return err
|
||||
}
|
||||
|
||||
// Restart 重启服务
|
||||
func Restart(name string) error {
|
||||
_, err := shell.Execf("systemctl restart %s", name)
|
||||
_, err := shell.ExecfWithTimeout(2*time.Minute, "systemctl restart %s", name)
|
||||
return err
|
||||
}
|
||||
|
||||
// Reload 重载服务
|
||||
func Reload(name string) error {
|
||||
_, err := shell.Execf("systemctl reload %s", name)
|
||||
_, err := shell.ExecfWithTimeout(2*time.Minute, "systemctl reload %s", name)
|
||||
return err
|
||||
}
|
||||
|
||||
// Enable 启用服务
|
||||
func Enable(name string) error {
|
||||
_, err := shell.Execf("systemctl enable %s", name)
|
||||
_, err := shell.ExecfWithTimeout(2*time.Minute, "systemctl enable %s", name)
|
||||
return err
|
||||
}
|
||||
|
||||
// Disable 禁用服务
|
||||
func Disable(name string) error {
|
||||
_, err := shell.Execf("systemctl disable %s", name)
|
||||
_, err := shell.ExecfWithTimeout(2*time.Minute, "systemctl disable %s", name)
|
||||
return err
|
||||
}
|
||||
|
||||
// Logs 获取服务日志
|
||||
func Logs(name string) (string, error) {
|
||||
return shell.Execf("journalctl -u %s", name)
|
||||
return shell.ExecfWithTimeout(2*time.Minute, "journalctl -u %s", name)
|
||||
}
|
||||
|
||||
// LogsTail 获取服务日志
|
||||
func LogsTail(name string, lines int) (string, error) {
|
||||
return shell.Execf("journalctl -u %s --lines %d", name, lines)
|
||||
return shell.ExecfWithTimeout(2*time.Minute, "journalctl -u %s --lines %d", name, lines)
|
||||
}
|
||||
|
||||
// LogsClear 清空服务日志
|
||||
|
||||
@@ -32,4 +32,5 @@ type WebsiteSetting struct {
|
||||
Rewrite string `json:"rewrite"`
|
||||
Raw string `json:"raw"`
|
||||
Log string `json:"log"`
|
||||
ErrorLog string `json:"error_log"`
|
||||
}
|
||||
|
||||
@@ -6,7 +6,7 @@ VITE_PUBLIC_PATH = '/'
|
||||
# 是否hash路由模式
|
||||
VITE_USE_HASH = false
|
||||
|
||||
# axios base api
|
||||
# base api
|
||||
VITE_BASE_API = '/api'
|
||||
|
||||
# 是否启用代理(只对本地vite server生效)
|
||||
|
||||
+9
-9
@@ -8,7 +8,7 @@
|
||||
},
|
||||
"license": "MIT",
|
||||
"repository": {
|
||||
"url": "https://github.com/tnb-labs/panel-frontend"
|
||||
"url": "https://github.com/tnb-labs/panel"
|
||||
},
|
||||
"scripts": {
|
||||
"dev": "vite",
|
||||
@@ -23,6 +23,7 @@
|
||||
"gen-auto-import": "tsx gen-auto-import.ts"
|
||||
},
|
||||
"dependencies": {
|
||||
"@alova/adapter-xhr": "^2.1.1",
|
||||
"@eslint/eslintrc": "^3.2.0",
|
||||
"@fontsource-variable/jetbrains-mono": "^5.1.1",
|
||||
"@guolao/vue-monaco-editor": "^1.5.4",
|
||||
@@ -36,7 +37,6 @@
|
||||
"@xterm/addon-webgl": "^0.18.0",
|
||||
"@xterm/xterm": "^5.5.0",
|
||||
"alova": "^3.2.7",
|
||||
"axios": "^1.7.9",
|
||||
"cronstrue": "^2.52.0",
|
||||
"echarts": "^5.6.0",
|
||||
"install": "^0.13.0",
|
||||
@@ -45,7 +45,7 @@
|
||||
"marked": "^15.0.4",
|
||||
"mitt": "^3.0.1",
|
||||
"node-forge": "^1.3.1",
|
||||
"pinia": "^2.3.0",
|
||||
"pinia": "^3.0.0",
|
||||
"pinia-plugin-persistedstate": "^4.2.0",
|
||||
"remove": "^0.1.5",
|
||||
"vue": "^3.5.13",
|
||||
@@ -62,7 +62,7 @@
|
||||
"@types/luxon": "^3.4.2",
|
||||
"@types/node": "^22.10.2",
|
||||
"@types/node-forge": "^1.3.11",
|
||||
"@unocss/eslint-config": "^0.65.3",
|
||||
"@unocss/eslint-config": "^65.0.0",
|
||||
"@vitejs/plugin-vue": "^5.2.1",
|
||||
"@vue/eslint-config-prettier": "^10.1.0",
|
||||
"@vue/eslint-config-typescript": "^14.2.0",
|
||||
@@ -79,11 +79,11 @@
|
||||
"prettier-plugin-organize-imports": "^4.1.0",
|
||||
"sass": "^1.83.0",
|
||||
"tsx": "^4.19.2",
|
||||
"typescript": "5.7.2",
|
||||
"unocss": "^0.65.3",
|
||||
"unplugin-auto-import": "^0.19.0",
|
||||
"unplugin-icons": "^0.22.0",
|
||||
"unplugin-vue-components": "^0.28.0",
|
||||
"typescript": "5.7.3",
|
||||
"unocss": "^65.0.0",
|
||||
"unplugin-auto-import": "^19.0.0",
|
||||
"unplugin-icons": "^22.0.0",
|
||||
"unplugin-vue-components": "^28.0.0",
|
||||
"vite": "^6.0.6",
|
||||
"vite-plugin-html": "^3.2.2",
|
||||
"vite-plugin-mock": "^3.0.2",
|
||||
|
||||
Generated
+1195
-1245
File diff suppressed because it is too large
Load Diff
@@ -1,9 +1,6 @@
|
||||
import type { AxiosResponse } from 'axios'
|
||||
|
||||
import { request } from '@/utils'
|
||||
import { http } from '@/utils'
|
||||
|
||||
export default {
|
||||
// 运行评分
|
||||
test: (name: string, multi: boolean): Promise<AxiosResponse<any>> =>
|
||||
request.post('/apps/benchmark/test', { name, multi })
|
||||
test: (name: string, multi: boolean): any => http.Post('/apps/benchmark/test', { name, multi })
|
||||
}
|
||||
|
||||
@@ -1,4 +1,6 @@
|
||||
import { http } from '@/utils'
|
||||
|
||||
export const getConfig = () => http.Get('/apps/docker/config')
|
||||
export const updateConfig = (config: string) => http.Post('/apps/docker/config', { config })
|
||||
export default {
|
||||
getConfig: (): any => http.Get('/apps/docker/config'),
|
||||
updateConfig: (config: string): any => http.Post('/apps/docker/config', { config })
|
||||
}
|
||||
|
||||
@@ -1,24 +1,19 @@
|
||||
import type { AxiosResponse } from 'axios'
|
||||
|
||||
import { request } from '@/utils'
|
||||
import { http } from '@/utils'
|
||||
|
||||
export default {
|
||||
// 保护列表
|
||||
jails: (page: number, limit: number): Promise<AxiosResponse<any>> =>
|
||||
request.get('/apps/fail2ban/jails', { params: { page, limit } }),
|
||||
jails: (page: number, limit: number): any =>
|
||||
http.Get('/apps/fail2ban/jails', { params: { page, limit } }),
|
||||
// 添加保护
|
||||
add: (data: any): Promise<AxiosResponse<any>> => request.post('/apps/fail2ban/jails', data),
|
||||
add: (data: any): any => http.Post('/apps/fail2ban/jails', data),
|
||||
// 删除保护
|
||||
delete: (name: string): Promise<AxiosResponse<any>> =>
|
||||
request.delete('/apps/fail2ban/jails', { data: { name } }),
|
||||
delete: (name: string): any => http.Delete('/apps/fail2ban/jails', { name }),
|
||||
// 封禁列表
|
||||
jail: (name: string): Promise<AxiosResponse<any>> => request.get('/apps/fail2ban/jails/' + name),
|
||||
jail: (name: string): any => http.Get('/apps/fail2ban/jails/' + name),
|
||||
// 解封 IP
|
||||
unban: (name: string, ip: string): Promise<AxiosResponse<any>> =>
|
||||
request.post('/apps/fail2ban/unban', { name, ip }),
|
||||
unban: (name: string, ip: string): any => http.Post('/apps/fail2ban/unban', { name, ip }),
|
||||
// 获取白名单
|
||||
whitelist: (): Promise<AxiosResponse<any>> => request.get('/apps/fail2ban/whiteList'),
|
||||
whitelist: (): any => http.Get('/apps/fail2ban/whiteList'),
|
||||
// 设置白名单
|
||||
setWhitelist: (ip: string): Promise<AxiosResponse<any>> =>
|
||||
request.post('/apps/fail2ban/whiteList', { ip })
|
||||
setWhitelist: (ip: string): any => http.Post('/apps/fail2ban/whiteList', { ip })
|
||||
}
|
||||
|
||||
@@ -1,12 +1,8 @@
|
||||
import type { AxiosResponse } from 'axios'
|
||||
|
||||
import { request } from '@/utils'
|
||||
import { http } from '@/utils'
|
||||
|
||||
export default {
|
||||
// 获取配置
|
||||
config: (name: string): Promise<AxiosResponse<any>> =>
|
||||
request.get('/apps/frp/config', { params: { name } }),
|
||||
config: (name: string): any => http.Get('/apps/frp/config', { params: { name } }),
|
||||
// 保存配置
|
||||
saveConfig: (name: string, config: string): Promise<AxiosResponse<any>> =>
|
||||
request.post('/apps/frp/config', { name, config })
|
||||
saveConfig: (name: string, config: string): any => http.Post('/apps/frp/config', { name, config })
|
||||
}
|
||||
|
||||
@@ -1,11 +1,8 @@
|
||||
import type { AxiosResponse } from 'axios'
|
||||
|
||||
import { request } from '@/utils'
|
||||
import { http } from '@/utils'
|
||||
|
||||
export default {
|
||||
// 获取配置
|
||||
config: (): Promise<AxiosResponse<any>> => request.get('/apps/gitea/config'),
|
||||
config: (): any => http.Get('/apps/gitea/config'),
|
||||
// 保存配置
|
||||
saveConfig: (config: string): Promise<AxiosResponse<any>> =>
|
||||
request.post('/apps/gitea/config', { config })
|
||||
saveConfig: (config: string): any => http.Post('/apps/gitea/config', { config })
|
||||
}
|
||||
|
||||
@@ -1,8 +1,7 @@
|
||||
import { http } from '@/utils'
|
||||
|
||||
// 负载状态
|
||||
export const getLoad = () => http.Get('/apps/memcached/load')
|
||||
// 获取配置
|
||||
export const getConfig = () => http.Get('/apps/memcached/config')
|
||||
// 保存配置
|
||||
export const updateConfig = (config: string) => http.Post('/apps/memcached/config', { config })
|
||||
export default {
|
||||
getLoad: (): any => http.Get('/apps/memcached/load'),
|
||||
getConfig: (): any => http.Get('/apps/memcached/config'),
|
||||
updateConfig: (config: string): any => http.Post('/apps/memcached/config', { config })
|
||||
}
|
||||
|
||||
@@ -1,26 +1,20 @@
|
||||
import type { AxiosResponse } from 'axios'
|
||||
|
||||
import { request } from '@/utils'
|
||||
import { http } from '@/utils'
|
||||
|
||||
export default {
|
||||
// 负载状态
|
||||
load: (): Promise<AxiosResponse<any>> => request.get('/apps/mysql/load'),
|
||||
load: (): any => http.Get('/apps/mysql/load'),
|
||||
// 获取配置
|
||||
config: (): Promise<AxiosResponse<any>> => request.get('/apps/mysql/config'),
|
||||
config: (): any => http.Get('/apps/mysql/config'),
|
||||
// 保存配置
|
||||
saveConfig: (config: string): Promise<AxiosResponse<any>> =>
|
||||
request.post('/apps/mysql/config', { config }),
|
||||
// 获取错误日志
|
||||
errorLog: (): Promise<AxiosResponse<any>> => request.get('/apps/mysql/errorLog'),
|
||||
saveConfig: (config: string): any => http.Post('/apps/mysql/config', { config }),
|
||||
// 清空错误日志
|
||||
clearErrorLog: (): Promise<AxiosResponse<any>> => request.post('/apps/mysql/clearErrorLog'),
|
||||
clearErrorLog: (): any => http.Post('/apps/mysql/clearErrorLog'),
|
||||
// 获取慢查询日志
|
||||
slowLog: (): Promise<AxiosResponse<any>> => request.get('/apps/mysql/slowLog'),
|
||||
slowLog: (): any => http.Get('/apps/mysql/slowLog'),
|
||||
// 清空慢查询日志
|
||||
clearSlowLog: (): Promise<AxiosResponse<any>> => request.post('/apps/mysql/clearSlowLog'),
|
||||
clearSlowLog: (): any => http.Post('/apps/mysql/clearSlowLog'),
|
||||
// 获取 root 密码
|
||||
rootPassword: (): Promise<AxiosResponse<any>> => request.get('/apps/mysql/rootPassword'),
|
||||
rootPassword: (): any => http.Get('/apps/mysql/rootPassword'),
|
||||
// 修改 root 密码
|
||||
setRootPassword: (password: string): Promise<AxiosResponse<any>> =>
|
||||
request.post('/apps/mysql/rootPassword', { password })
|
||||
setRootPassword: (password: string): any => http.Post('/apps/mysql/rootPassword', { password })
|
||||
}
|
||||
|
||||
@@ -1,17 +1,14 @@
|
||||
import type { AxiosResponse } from 'axios'
|
||||
|
||||
import { request } from '@/utils'
|
||||
import { http } from '@/utils'
|
||||
|
||||
export default {
|
||||
// 负载状态
|
||||
load: (): Promise<AxiosResponse<any>> => request.get('/apps/nginx/load'),
|
||||
load: (): any => http.Get('/apps/nginx/load'),
|
||||
// 获取配置
|
||||
config: (): Promise<AxiosResponse<any>> => request.get('/apps/nginx/config'),
|
||||
config: (): any => http.Get('/apps/nginx/config'),
|
||||
// 保存配置
|
||||
saveConfig: (config: string): Promise<AxiosResponse<any>> =>
|
||||
request.post('/apps/nginx/config', { config }),
|
||||
saveConfig: (config: string): any => http.Post('/apps/nginx/config', { config }),
|
||||
// 获取错误日志
|
||||
errorLog: (): Promise<AxiosResponse<any>> => request.get('/apps/nginx/errorLog'),
|
||||
errorLog: (): any => http.Get('/apps/nginx/errorLog'),
|
||||
// 清空错误日志
|
||||
clearErrorLog: (): Promise<AxiosResponse<any>> => request.post('/apps/nginx/clearErrorLog')
|
||||
clearErrorLog: (): any => http.Post('/apps/nginx/clearErrorLog')
|
||||
}
|
||||
|
||||
@@ -1,44 +1,34 @@
|
||||
import type { AxiosResponse } from 'axios'
|
||||
|
||||
import { request } from '@/utils'
|
||||
import { http } from '@/utils'
|
||||
|
||||
export default {
|
||||
// 设为 CLI 版本
|
||||
setCli: (version: number): Promise<AxiosResponse<any>> =>
|
||||
request.post(`/apps/php${version}/setCli`),
|
||||
setCli: (version: number): any => http.Post(`/apps/php${version}/setCli`),
|
||||
// 获取配置
|
||||
config: (version: number): Promise<AxiosResponse<any>> =>
|
||||
request.get(`/apps/php${version}/config`),
|
||||
config: (version: number): any => http.Get(`/apps/php${version}/config`),
|
||||
// 保存配置
|
||||
saveConfig: (version: number, config: string): Promise<AxiosResponse<any>> =>
|
||||
request.post(`/apps/php${version}/config`, { config }),
|
||||
saveConfig: (version: number, config: string): any =>
|
||||
http.Post(`/apps/php${version}/config`, { config }),
|
||||
// 获取FPM配置
|
||||
fpmConfig: (version: number): Promise<AxiosResponse<any>> =>
|
||||
request.get(`/apps/php${version}/fpmConfig`),
|
||||
fpmConfig: (version: number): any => http.Get(`/apps/php${version}/fpmConfig`),
|
||||
// 保存FPM配置
|
||||
saveFPMConfig: (version: number, config: string): Promise<AxiosResponse<any>> =>
|
||||
request.post(`/apps/php${version}/fpmConfig`, { config }),
|
||||
saveFPMConfig: (version: number, config: string): any =>
|
||||
http.Post(`/apps/php${version}/fpmConfig`, { config }),
|
||||
// 负载状态
|
||||
load: (version: number): Promise<AxiosResponse<any>> => request.get(`/apps/php${version}/load`),
|
||||
load: (version: number): any => http.Get(`/apps/php${version}/load`),
|
||||
// 获取错误日志
|
||||
errorLog: (version: number): Promise<AxiosResponse<any>> =>
|
||||
request.get(`/apps/php${version}/errorLog`),
|
||||
errorLog: (version: number): any => http.Get(`/apps/php${version}/errorLog`),
|
||||
// 清空错误日志
|
||||
clearErrorLog: (version: number): Promise<AxiosResponse<any>> =>
|
||||
request.post(`/apps/php${version}/clearErrorLog`),
|
||||
clearErrorLog: (version: number): any => http.Post(`/apps/php${version}/clearErrorLog`),
|
||||
// 获取慢日志
|
||||
slowLog: (version: number): Promise<AxiosResponse<any>> =>
|
||||
request.get(`/apps/php${version}/slowLog`),
|
||||
slowLog: (version: number): any => http.Get(`/apps/php${version}/slowLog`),
|
||||
// 清空慢日志
|
||||
clearSlowLog: (version: number): Promise<AxiosResponse<any>> =>
|
||||
request.post(`/apps/php${version}/clearSlowLog`),
|
||||
clearSlowLog: (version: number): any => http.Post(`/apps/php${version}/clearSlowLog`),
|
||||
// 拓展列表
|
||||
extensions: (version: number): Promise<AxiosResponse<any>> =>
|
||||
request.get(`/apps/php${version}/extensions`),
|
||||
extensions: (version: number): any => http.Get(`/apps/php${version}/extensions`),
|
||||
// 安装拓展
|
||||
installExtension: (version: number, slug: string): Promise<AxiosResponse<any>> =>
|
||||
request.post(`/apps/php${version}/extensions`, { slug }),
|
||||
installExtension: (version: number, slug: string): any =>
|
||||
http.Post(`/apps/php${version}/extensions`, { slug }),
|
||||
// 卸载拓展
|
||||
uninstallExtension: (version: number, slug: string): Promise<AxiosResponse<any>> =>
|
||||
request.delete(`/apps/php${version}/extensions`, { data: { slug } })
|
||||
uninstallExtension: (version: number, slug: string): any =>
|
||||
http.Delete(`/apps/php${version}/extensions`, { slug })
|
||||
}
|
||||
|
||||
@@ -1,16 +1,12 @@
|
||||
import type { AxiosResponse } from 'axios'
|
||||
|
||||
import { request } from '@/utils'
|
||||
import { http } from '@/utils'
|
||||
|
||||
export default {
|
||||
// 获取信息
|
||||
info: (): Promise<AxiosResponse<any>> => request.get('/apps/phpmyadmin/info'),
|
||||
info: (): any => http.Get('/apps/phpmyadmin/info'),
|
||||
// 设置端口
|
||||
port: (port: number): Promise<AxiosResponse<any>> =>
|
||||
request.post('/apps/phpmyadmin/port', { port }),
|
||||
port: (port: number): any => http.Post('/apps/phpmyadmin/port', { port }),
|
||||
// 获取配置
|
||||
getConfig: (): Promise<AxiosResponse<any>> => request.get('/apps/phpmyadmin/config'),
|
||||
getConfig: (): any => http.Get('/apps/phpmyadmin/config'),
|
||||
// 保存配置
|
||||
saveConfig: (config: string): Promise<AxiosResponse<any>> =>
|
||||
request.post('/apps/phpmyadmin/config', { config })
|
||||
saveConfig: (config: string): any => http.Post('/apps/phpmyadmin/config', { config })
|
||||
}
|
||||
|
||||
@@ -1,16 +1,12 @@
|
||||
import type { AxiosResponse } from 'axios'
|
||||
|
||||
import { request } from '@/utils'
|
||||
import { http } from '@/utils'
|
||||
|
||||
export default {
|
||||
// 获取注册表配置
|
||||
registryConfig: (): Promise<AxiosResponse<any>> => request.get('/apps/podman/registryConfig'),
|
||||
registryConfig: (): any => http.Get('/apps/podman/registryConfig'),
|
||||
// 保存注册表配置
|
||||
saveRegistryConfig: (config: string): Promise<AxiosResponse<any>> =>
|
||||
request.post('/apps/podman/registryConfig', { config }),
|
||||
saveRegistryConfig: (config: string): any => http.Post('/apps/podman/registryConfig', { config }),
|
||||
// 获取存储配置
|
||||
storageConfig: (): Promise<AxiosResponse<any>> => request.get('/apps/podman/storageConfig'),
|
||||
storageConfig: (): any => http.Get('/apps/podman/storageConfig'),
|
||||
// 保存存储配置
|
||||
saveStorageConfig: (config: string): Promise<AxiosResponse<any>> =>
|
||||
request.post('/apps/podman/storageConfig', { config })
|
||||
saveStorageConfig: (config: string): any => http.Post('/apps/podman/storageConfig', { config })
|
||||
}
|
||||
|
||||
@@ -1,22 +1,18 @@
|
||||
import type { AxiosResponse } from 'axios'
|
||||
|
||||
import { request } from '@/utils'
|
||||
import { http } from '@/utils'
|
||||
|
||||
export default {
|
||||
// 负载状态
|
||||
load: (): Promise<AxiosResponse<any>> => request.get('/apps/postgresql/load'),
|
||||
load: (): any => http.Get('/apps/postgresql/load'),
|
||||
// 获取配置
|
||||
config: (): Promise<AxiosResponse<any>> => request.get('/apps/postgresql/config'),
|
||||
config: (): any => http.Get('/apps/postgresql/config'),
|
||||
// 保存配置
|
||||
saveConfig: (config: string): Promise<AxiosResponse<any>> =>
|
||||
request.post('/apps/postgresql/config', { config }),
|
||||
saveConfig: (config: string): any => http.Post('/apps/postgresql/config', { config }),
|
||||
// 获取用户配置
|
||||
userConfig: (): Promise<AxiosResponse<any>> => request.get('/apps/postgresql/userConfig'),
|
||||
userConfig: (): any => http.Get('/apps/postgresql/userConfig'),
|
||||
// 保存配置
|
||||
saveUserConfig: (config: string): Promise<AxiosResponse<any>> =>
|
||||
request.post('/apps/postgresql/userConfig', { config }),
|
||||
saveUserConfig: (config: string): any => http.Post('/apps/postgresql/userConfig', { config }),
|
||||
// 获取日志
|
||||
log: (): Promise<AxiosResponse<any>> => request.get('/apps/postgresql/log'),
|
||||
log: (): any => http.Get('/apps/postgresql/log'),
|
||||
// 清空错误日志
|
||||
clearLog: (): Promise<AxiosResponse<any>> => request.post('/apps/postgresql/clearLog')
|
||||
clearLog: (): any => http.Post('/apps/postgresql/clearLog')
|
||||
}
|
||||
|
||||
@@ -1,23 +1,19 @@
|
||||
import type { AxiosResponse } from 'axios'
|
||||
|
||||
import { request } from '@/utils'
|
||||
import { http } from '@/utils'
|
||||
|
||||
export default {
|
||||
// 列表
|
||||
list: (page: number, limit: number): Promise<AxiosResponse<any>> =>
|
||||
request.get('/apps/pureftpd/users', { params: { page, limit } }),
|
||||
list: (page: number, limit: number): any =>
|
||||
http.Get('/apps/pureftpd/users', { params: { page, limit } }),
|
||||
// 添加
|
||||
add: (username: string, password: string, path: string): Promise<AxiosResponse<any>> =>
|
||||
request.post('/apps/pureftpd/users', { username, password, path }),
|
||||
add: (username: string, password: string, path: string): any =>
|
||||
http.Post('/apps/pureftpd/users', { username, password, path }),
|
||||
// 删除
|
||||
delete: (username: string): Promise<AxiosResponse<any>> =>
|
||||
request.delete(`/apps/pureftpd/users/${username}`),
|
||||
delete: (username: string): any => http.Delete(`/apps/pureftpd/users/${username}`),
|
||||
// 修改密码
|
||||
changePassword: (username: string, password: string): Promise<AxiosResponse<any>> =>
|
||||
request.post(`/apps/pureftpd/users/${username}/password`, { password }),
|
||||
changePassword: (username: string, password: string): any =>
|
||||
http.Post(`/apps/pureftpd/users/${username}/password`, { password }),
|
||||
// 获取端口
|
||||
port: (): Promise<AxiosResponse<any>> => request.get('/apps/pureftpd/port'),
|
||||
port: (): any => http.Get('/apps/pureftpd/port'),
|
||||
// 修改端口
|
||||
setPort: (port: number): Promise<AxiosResponse<any>> =>
|
||||
request.post('/apps/pureftpd/port', { port })
|
||||
updatePort: (port: number): any => http.Post('/apps/pureftpd/port', { port })
|
||||
}
|
||||
|
||||
@@ -1,13 +1,10 @@
|
||||
import type { AxiosResponse } from 'axios'
|
||||
|
||||
import { request } from '@/utils'
|
||||
import { http } from '@/utils'
|
||||
|
||||
export default {
|
||||
// 负载状态
|
||||
load: (): Promise<AxiosResponse<any>> => request.get('/apps/redis/load'),
|
||||
load: (): any => http.Get('/apps/redis/load'),
|
||||
// 获取配置
|
||||
config: (): Promise<AxiosResponse<any>> => request.get('/apps/redis/config'),
|
||||
config: (): any => http.Get('/apps/redis/config'),
|
||||
// 保存配置
|
||||
saveConfig: (config: string): Promise<AxiosResponse<any>> =>
|
||||
request.post('/apps/redis/config', { config })
|
||||
saveConfig: (config: string): any => http.Post('/apps/redis/config', { config })
|
||||
}
|
||||
|
||||
@@ -1,23 +1,17 @@
|
||||
import type { AxiosResponse } from 'axios'
|
||||
|
||||
import { request } from '@/utils'
|
||||
import { http } from '@/utils'
|
||||
|
||||
export default {
|
||||
// 获取配置
|
||||
config: (): Promise<AxiosResponse<any>> => request.get('/apps/rsync/config'),
|
||||
config: (): any => http.Get('/apps/rsync/config'),
|
||||
// 保存配置
|
||||
saveConfig: (config: string): Promise<AxiosResponse<any>> =>
|
||||
request.post('/apps/rsync/config', { config }),
|
||||
saveConfig: (config: string): any => http.Post('/apps/rsync/config', { config }),
|
||||
// 模块列表
|
||||
modules: (page: number, limit: number): Promise<AxiosResponse<any>> =>
|
||||
request.get('/apps/rsync/modules', { params: { page, limit } }),
|
||||
modules: (page: number, limit: number): any =>
|
||||
http.Get('/apps/rsync/modules', { params: { page, limit } }),
|
||||
// 添加模块
|
||||
addModule: (module: any): Promise<AxiosResponse<any>> =>
|
||||
request.post('/apps/rsync/modules', module),
|
||||
addModule: (module: any): any => http.Post('/apps/rsync/modules', module),
|
||||
// 删除模块
|
||||
deleteModule: (name: string): Promise<AxiosResponse<any>> =>
|
||||
request.delete('/apps/rsync/modules/' + name),
|
||||
deleteModule: (name: string): any => http.Delete(`/apps/rsync/modules/${name}`),
|
||||
// 更新模块
|
||||
updateModule: (name: string, module: any): Promise<AxiosResponse<any>> =>
|
||||
request.post('/apps/rsync/modules/' + name, module)
|
||||
updateModule: (name: string, module: any): any => http.Post(`/apps/rsync/modules/${name}`, module)
|
||||
}
|
||||
|
||||
@@ -1,14 +1,11 @@
|
||||
import type { AxiosResponse } from 'axios'
|
||||
|
||||
import { request } from '@/utils'
|
||||
import { http } from '@/utils'
|
||||
|
||||
export default {
|
||||
// 列表
|
||||
list: (page: number, limit: number): Promise<AxiosResponse<any>> =>
|
||||
request.get('/apps/s3fs/mounts', { params: { page, limit } }),
|
||||
mounts: (page: number, limit: number): any =>
|
||||
http.Get('/apps/s3fs/mounts', { params: { page, limit } }),
|
||||
// 添加
|
||||
add: (data: any): Promise<AxiosResponse<any>> => request.post('/apps/s3fs/mounts', data),
|
||||
add: (data: any): any => http.Post('/apps/s3fs/mounts', data),
|
||||
// 删除
|
||||
delete: (id: number): Promise<AxiosResponse<any>> =>
|
||||
request.delete('/apps/s3fs/mounts', { data: { id } })
|
||||
delete: (id: number): any => http.Delete('/apps/s3fs/mounts', { id })
|
||||
}
|
||||
|
||||
@@ -1,47 +1,38 @@
|
||||
import type { AxiosResponse } from 'axios'
|
||||
|
||||
import { request } from '@/utils'
|
||||
import { http } from '@/utils'
|
||||
|
||||
export default {
|
||||
// 服务名称
|
||||
service: (): Promise<AxiosResponse<any>> => request.get('/apps/supervisor/service'),
|
||||
service: (): any => http.Get('/apps/supervisor/service'),
|
||||
// 获取错误日志
|
||||
log: (): Promise<AxiosResponse<any>> => request.get('/apps/supervisor/log'),
|
||||
log: (): any => http.Get('/apps/supervisor/log'),
|
||||
// 清空错误日志
|
||||
clearLog: (): Promise<AxiosResponse<any>> => request.post('/apps/supervisor/clearLog'),
|
||||
clearLog: (): any => http.Post('/apps/supervisor/clearLog'),
|
||||
// 获取配置
|
||||
config: (): Promise<AxiosResponse<any>> => request.get('/apps/supervisor/config'),
|
||||
config: (): any => http.Get('/apps/supervisor/config'),
|
||||
// 保存配置
|
||||
saveConfig: (config: string): Promise<AxiosResponse<any>> =>
|
||||
request.post('/apps/supervisor/config', { config }),
|
||||
saveConfig: (config: string): any => http.Post('/apps/supervisor/config', { config }),
|
||||
// 进程列表
|
||||
processes: (page: number, limit: number): Promise<AxiosResponse<any>> =>
|
||||
request.get('/apps/supervisor/processes', { params: { page, limit } }),
|
||||
processes: (page: number, limit: number): any =>
|
||||
http.Get('/apps/supervisor/processes', { params: { page, limit } }),
|
||||
// 进程启动
|
||||
startProcess: (process: string): Promise<AxiosResponse<any>> =>
|
||||
request.post(`/apps/supervisor/processes/${process}/start`),
|
||||
startProcess: (process: string): any => http.Post(`/apps/supervisor/processes/${process}/start`),
|
||||
// 进程停止
|
||||
stopProcess: (process: string): Promise<AxiosResponse<any>> =>
|
||||
request.post(`/apps/supervisor/processes/${process}/stop`),
|
||||
stopProcess: (process: string): any => http.Post(`/apps/supervisor/processes/${process}/stop`),
|
||||
// 进程重启
|
||||
restartProcess: (process: string): Promise<AxiosResponse<any>> =>
|
||||
request.post(`/apps/supervisor/processes/${process}/restart`),
|
||||
restartProcess: (process: string): any =>
|
||||
http.Post(`/apps/supervisor/processes/${process}/restart`),
|
||||
// 进程日志
|
||||
processLog: (process: string): Promise<AxiosResponse<any>> =>
|
||||
request.get(`/apps/supervisor/processes/${process}/log`),
|
||||
processLog: (process: string): any => http.Get(`/apps/supervisor/processes/${process}/log`),
|
||||
// 清空进程日志
|
||||
clearProcessLog: (process: string): Promise<AxiosResponse<any>> =>
|
||||
request.post(`/apps/supervisor/processes/${process}/clearLog`),
|
||||
clearProcessLog: (process: string): any =>
|
||||
http.Post(`/apps/supervisor/processes/${process}/clearLog`),
|
||||
// 进程配置
|
||||
processConfig: (process: string): Promise<AxiosResponse<any>> =>
|
||||
request.get(`/apps/supervisor/processes/${process}`),
|
||||
processConfig: (process: string): any => http.Get(`/apps/supervisor/processes/${process}`),
|
||||
// 保存进程配置
|
||||
saveProcessConfig: (process: string, config: string): Promise<AxiosResponse<any>> =>
|
||||
request.post(`/apps/supervisor/processes/${process}`, { config }),
|
||||
saveProcessConfig: (process: string, config: string): any =>
|
||||
http.Post(`/apps/supervisor/processes/${process}`, { config }),
|
||||
// 创建进程
|
||||
createProcess: (process: any): Promise<AxiosResponse<any>> =>
|
||||
request.post('/apps/supervisor/processes', process),
|
||||
createProcess: (process: any): any => http.Post('/apps/supervisor/processes', process),
|
||||
// 删除进程
|
||||
deleteProcess: (process: string): Promise<AxiosResponse<any>> =>
|
||||
request.delete(`/apps/supervisor/processes/${process}`)
|
||||
deleteProcess: (process: string): any => http.Delete(`/apps/supervisor/processes/${process}`)
|
||||
}
|
||||
|
||||
@@ -1,39 +1,31 @@
|
||||
import type { AxiosResponse } from 'axios'
|
||||
|
||||
import { request } from '@/utils'
|
||||
import { http } from '@/utils'
|
||||
|
||||
export default {
|
||||
// DNS
|
||||
dns: (): Promise<AxiosResponse<any>> => request.get('/apps/toolbox/dns'),
|
||||
dns: (): any => http.Get('/apps/toolbox/dns'),
|
||||
// 设置 DNS
|
||||
updateDns: (dns1: string, dns2: string): Promise<AxiosResponse<any>> =>
|
||||
request.post('/apps/toolbox/dns', { dns1, dns2 }),
|
||||
updateDns: (dns1: string, dns2: string): any => http.Post('/apps/toolbox/dns', { dns1, dns2 }),
|
||||
// SWAP
|
||||
swap: (): Promise<AxiosResponse<any>> => request.get('/apps/toolbox/swap'),
|
||||
swap: (): any => http.Get('/apps/toolbox/swap'),
|
||||
// 设置 SWAP
|
||||
updateSwap: (size: number): Promise<AxiosResponse<any>> =>
|
||||
request.post('/apps/toolbox/swap', { size }),
|
||||
updateSwap: (size: number): any => http.Post('/apps/toolbox/swap', { size }),
|
||||
// 时区
|
||||
timezone: (): Promise<AxiosResponse<any>> => request.get('/apps/toolbox/timezone'),
|
||||
timezone: (): any => http.Get('/apps/toolbox/timezone'),
|
||||
// 设置时区
|
||||
updateTimezone: (timezone: string): Promise<AxiosResponse<any>> =>
|
||||
request.post('/apps/toolbox/timezone', { timezone }),
|
||||
updateTimezone: (timezone: string): any => http.Post('/apps/toolbox/timezone', { timezone }),
|
||||
// 设置时间
|
||||
updateTime: (time: string): Promise<AxiosResponse<any>> =>
|
||||
request.post('/apps/toolbox/time', { time }),
|
||||
updateTime: (time: string): any => http.Post('/apps/toolbox/time', { time }),
|
||||
// 同步时间
|
||||
syncTime: (): Promise<AxiosResponse<any>> => request.post('/apps/toolbox/syncTime'),
|
||||
syncTime: (): any => http.Post('/apps/toolbox/syncTime'),
|
||||
// 主机名
|
||||
hostname: (): Promise<AxiosResponse<any>> => request.get('/apps/toolbox/hostname'),
|
||||
hostname: (): any => http.Get('/apps/toolbox/hostname'),
|
||||
// Hosts
|
||||
hosts: (): Promise<AxiosResponse<any>> => request.get('/apps/toolbox/hosts'),
|
||||
hosts: (): any => http.Get('/apps/toolbox/hosts'),
|
||||
// 设置主机名
|
||||
updateHostname: (hostname: string): Promise<AxiosResponse<any>> =>
|
||||
request.post('/apps/toolbox/hostname', { hostname }),
|
||||
updateHostname: (hostname: string): any => http.Post('/apps/toolbox/hostname', { hostname }),
|
||||
// 设置 Hosts
|
||||
updateHosts: (hosts: string): Promise<AxiosResponse<any>> =>
|
||||
request.post('/apps/toolbox/hosts', { hosts }),
|
||||
updateHosts: (hosts: string): any => http.Post('/apps/toolbox/hosts', { hosts }),
|
||||
// 设置 Root 密码
|
||||
updateRootPassword: (password: string): Promise<AxiosResponse<any>> =>
|
||||
request.post('/apps/toolbox/rootPassword', { password })
|
||||
updateRootPassword: (password: string): any =>
|
||||
http.Post('/apps/toolbox/rootPassword', { password })
|
||||
}
|
||||
|
||||
@@ -1,25 +1,19 @@
|
||||
import type { AxiosResponse } from 'axios'
|
||||
|
||||
import { request } from '@/utils'
|
||||
import { http } from '@/utils'
|
||||
|
||||
export default {
|
||||
// 获取应用列表
|
||||
list: (page: number, limit: number): Promise<AxiosResponse<any>> =>
|
||||
request.get('/app/list', { params: { page, limit } }),
|
||||
list: (page: number, limit: number): any => http.Get('/app/list', { params: { page, limit } }),
|
||||
// 安装应用
|
||||
install: (slug: string, channel: string | null): Promise<AxiosResponse<any>> =>
|
||||
request.post('/app/install', { slug, channel }),
|
||||
install: (slug: string, channel: string | null): any =>
|
||||
http.Post('/app/install', { slug, channel }),
|
||||
// 卸载应用
|
||||
uninstall: (slug: string): Promise<AxiosResponse<any>> =>
|
||||
request.post('/app/uninstall', { slug }),
|
||||
uninstall: (slug: string): any => http.Post('/app/uninstall', { slug }),
|
||||
// 更新应用
|
||||
update: (slug: string): Promise<AxiosResponse<any>> => request.post('/app/update', { slug }),
|
||||
update: (slug: string): any => http.Post('/app/update', { slug }),
|
||||
// 设置首页显示
|
||||
updateShow: (slug: string, show: boolean): Promise<AxiosResponse<any>> =>
|
||||
request.post('/app/updateShow', { slug, show }),
|
||||
updateShow: (slug: string, show: boolean): any => http.Post('/app/updateShow', { slug, show }),
|
||||
// 应用是否已安装
|
||||
isInstalled: (slug: string): Promise<AxiosResponse<any>> =>
|
||||
request.get('/app/isInstalled', { params: { slug } }),
|
||||
isInstalled: (slug: string): any => http.Get('/app/isInstalled', { params: { slug } }),
|
||||
// 更新缓存
|
||||
updateCache: (): Promise<AxiosResponse<any>> => request.get('/app/updateCache')
|
||||
updateCache: (): any => http.Get('/app/updateCache')
|
||||
}
|
||||
|
||||
@@ -1,24 +1,21 @@
|
||||
import type { AxiosResponse } from 'axios'
|
||||
|
||||
import { request } from '@/utils'
|
||||
import { http } from '@/utils'
|
||||
|
||||
export default {
|
||||
// 获取备份列表
|
||||
list: (type: string, page: number, limit: number): Promise<AxiosResponse<any>> =>
|
||||
request.get(`/backup/${type}`, { params: { page, limit } }),
|
||||
list: (type: string, page: number, limit: number): any =>
|
||||
http.Get(`/backup/${type}`, { params: { page, limit } }),
|
||||
// 创建备份
|
||||
create: (type: string, target: string, path: string): Promise<AxiosResponse<any>> =>
|
||||
request.post(`/backup/${type}`, { target, path }),
|
||||
create: (type: string, target: string, path: string): any =>
|
||||
http.Post(`/backup/${type}`, { target, path }),
|
||||
// 上传备份
|
||||
upload: (type: string, formData: FormData): Promise<AxiosResponse<any>> => {
|
||||
return request.post(`/backup/${type}/upload`, formData, {
|
||||
upload: (type: string, formData: FormData): any => {
|
||||
return http.Post(`/backup/${type}/upload`, formData, {
|
||||
headers: { 'Content-Type': 'multipart/form-data' }
|
||||
})
|
||||
},
|
||||
// 删除备份
|
||||
delete: (type: string, file: string): Promise<AxiosResponse<any>> =>
|
||||
request.delete(`/backup/${type}/delete`, { data: { file } }),
|
||||
delete: (type: string, file: string): any => http.Delete(`/backup/${type}/delete`, { file }),
|
||||
// 恢复备份
|
||||
restore: (type: string, file: string, target: string): Promise<AxiosResponse<any>> =>
|
||||
request.post(`/backup/${type}/restore`, { file, target })
|
||||
restore: (type: string, file: string, target: string): any =>
|
||||
http.Post(`/backup/${type}/restore`, { file, target })
|
||||
}
|
||||
|
||||
@@ -1,68 +1,56 @@
|
||||
import type { AxiosResponse } from 'axios'
|
||||
|
||||
import { request } from '@/utils'
|
||||
import { http } from '@/utils'
|
||||
|
||||
export default {
|
||||
// CA 供应商列表
|
||||
caProviders: (): Promise<AxiosResponse<any>> => request.get('/cert/caProviders'),
|
||||
caProviders: (): any => http.Get('/cert/caProviders'),
|
||||
// DNS 供应商列表
|
||||
dnsProviders: (): Promise<AxiosResponse<any>> => request.get('/cert/dnsProviders'),
|
||||
dnsProviders: (): any => http.Get('/cert/dnsProviders'),
|
||||
// 证书算法列表
|
||||
algorithms: (): Promise<AxiosResponse<any>> => request.get('/cert/algorithms'),
|
||||
algorithms: (): any => http.Get('/cert/algorithms'),
|
||||
// ACME 账号列表
|
||||
accounts: (page: number, limit: number): Promise<AxiosResponse<any>> =>
|
||||
request.get('/cert/account', { params: { page, limit } }),
|
||||
accounts: (page: number, limit: number): any =>
|
||||
http.Get('/cert/account', { params: { page, limit } }),
|
||||
// ACME 账号详情
|
||||
accountInfo: (id: number): Promise<AxiosResponse<any>> => request.get(`/cert/account/${id}`),
|
||||
accountInfo: (id: number): any => http.Get(`/cert/account/${id}`),
|
||||
// ACME 账号添加
|
||||
accountCreate: (data: any): Promise<AxiosResponse<any>> => request.post('/cert/account', data),
|
||||
accountCreate: (data: any): any => http.Post('/cert/account', data),
|
||||
// ACME 账号更新
|
||||
accountUpdate: (id: number, data: any): Promise<AxiosResponse<any>> =>
|
||||
request.put(`/cert/account/${id}`, data),
|
||||
accountUpdate: (id: number, data: any): any => http.Put(`/cert/account/${id}`, data),
|
||||
// ACME 账号删除
|
||||
accountDelete: (id: number): Promise<AxiosResponse<any>> => request.delete(`/cert/account/${id}`),
|
||||
accountDelete: (id: number): any => http.Delete(`/cert/account/${id}`),
|
||||
// DNS 记录列表
|
||||
dns: (page: number, limit: number): Promise<AxiosResponse<any>> =>
|
||||
request.get('/cert/dns', { params: { page, limit } }),
|
||||
dns: (page: number, limit: number): any => http.Get('/cert/dns', { params: { page, limit } }),
|
||||
// DNS 记录详情
|
||||
dnsInfo: (id: number): Promise<AxiosResponse<any>> => request.get(`/cert/dns/${id}`),
|
||||
dnsInfo: (id: number): any => http.Get(`/cert/dns/${id}`),
|
||||
// DNS 记录添加
|
||||
dnsCreate: (data: any): Promise<AxiosResponse<any>> => request.post('/cert/dns', data),
|
||||
dnsCreate: (data: any): any => http.Post('/cert/dns', data),
|
||||
// DNS 记录更新
|
||||
dnsUpdate: (id: number, data: any): Promise<AxiosResponse<any>> =>
|
||||
request.put(`/cert/dns/${id}`, data),
|
||||
dnsUpdate: (id: number, data: any): any => http.Put(`/cert/dns/${id}`, data),
|
||||
// DNS 记录删除
|
||||
dnsDelete: (id: number): Promise<AxiosResponse<any>> => request.delete(`/cert/dns/${id}`),
|
||||
dnsDelete: (id: number): any => http.Delete(`/cert/dns/${id}`),
|
||||
// 证书列表
|
||||
certs: (page: number, limit: number): Promise<AxiosResponse<any>> =>
|
||||
request.get('/cert/cert', { params: { page, limit } }),
|
||||
certs: (page: number, limit: number): any => http.Get('/cert/cert', { params: { page, limit } }),
|
||||
// 证书详情
|
||||
certInfo: (id: number): Promise<AxiosResponse<any>> => request.get(`/cert/cert/${id}`),
|
||||
certInfo: (id: number): any => http.Get(`/cert/cert/${id}`),
|
||||
// 证书上传
|
||||
certUpload: (data: any): Promise<AxiosResponse<any>> => request.post('/cert/cert/upload', data),
|
||||
certUpload: (data: any): any => http.Post('/cert/cert/upload', data),
|
||||
// 证书添加
|
||||
certCreate: (data: any): Promise<AxiosResponse<any>> => request.post('/cert/cert', data),
|
||||
certCreate: (data: any): any => http.Post('/cert/cert', data),
|
||||
// 证书更新
|
||||
certUpdate: (id: number, data: any): Promise<AxiosResponse<any>> =>
|
||||
request.put(`/cert/cert/${id}`, data),
|
||||
certUpdate: (id: number, data: any): any => http.Put(`/cert/cert/${id}`, data),
|
||||
// 证书删除
|
||||
certDelete: (id: number): Promise<AxiosResponse<any>> => request.delete(`/cert/cert/${id}`),
|
||||
certDelete: (id: number): any => http.Delete(`/cert/cert/${id}`),
|
||||
// 证书自动签发
|
||||
obtainAuto: (id: number): Promise<AxiosResponse<any>> =>
|
||||
request.post(`/cert/cert/${id}/obtainAuto`, { id }),
|
||||
obtainAuto: (id: number): any => http.Post(`/cert/cert/${id}/obtainAuto`, { id }),
|
||||
// 证书手动签发
|
||||
obtainManual: (id: number): Promise<AxiosResponse<any>> =>
|
||||
request.post(`/cert/cert/${id}/obtainManual`, { id }),
|
||||
obtainManual: (id: number): any => http.Post(`/cert/cert/${id}/obtainManual`, { id }),
|
||||
// 证书自签名签发
|
||||
obtainSelfSigned: (id: number): Promise<AxiosResponse<any>> =>
|
||||
request.post(`/cert/cert/${id}/obtainSelfSigned`, { id }),
|
||||
obtainSelfSigned: (id: number): any => http.Post(`/cert/cert/${id}/obtainSelfSigned`, { id }),
|
||||
// 续签
|
||||
renew: (id: number): Promise<AxiosResponse<any>> =>
|
||||
request.post(`/cert/cert/${id}/renew`, { id }),
|
||||
renew: (id: number): any => http.Post(`/cert/cert/${id}/renew`, { id }),
|
||||
// 获取 DNS 记录
|
||||
manualDNS: (id: number): Promise<AxiosResponse<any>> =>
|
||||
request.post(`/cert/cert/${id}/manualDNS`, { id }),
|
||||
manualDNS: (id: number): any => http.Post(`/cert/cert/${id}/manualDNS`, { id }),
|
||||
// 部署
|
||||
deploy: (id: number, website_id: number): Promise<AxiosResponse<any>> =>
|
||||
request.post(`/cert/cert/${id}/deploy`, { id, website_id })
|
||||
deploy: (id: number, website_id: number): any =>
|
||||
http.Post(`/cert/cert/${id}/deploy`, { id, website_id })
|
||||
}
|
||||
|
||||
@@ -1,73 +1,57 @@
|
||||
import type { AxiosResponse } from 'axios'
|
||||
|
||||
import { request } from '@/utils'
|
||||
import { http } from '@/utils'
|
||||
|
||||
export default {
|
||||
// 获取容器列表
|
||||
containerList: (page: number, limit: number): Promise<AxiosResponse<any>> =>
|
||||
request.get('/container/container', { params: { page, limit } }),
|
||||
containerList: (page: number, limit: number): any =>
|
||||
http.Get('/container/container', { params: { page, limit } }),
|
||||
// 添加容器
|
||||
containerCreate: (config: any): Promise<AxiosResponse<any>> =>
|
||||
request.post('/container/container', config),
|
||||
containerCreate: (config: any): any => http.Post('/container/container', config),
|
||||
// 删除容器
|
||||
containerRemove: (id: string): Promise<AxiosResponse<any>> =>
|
||||
request.delete(`/container/container/${id}`),
|
||||
containerRemove: (id: string): any => http.Delete(`/container/container/${id}`),
|
||||
// 启动容器
|
||||
containerStart: (id: string): Promise<AxiosResponse<any>> =>
|
||||
request.post(`/container/container/${id}/start`),
|
||||
containerStart: (id: string): any => http.Post(`/container/container/${id}/start`),
|
||||
// 停止容器
|
||||
containerStop: (id: string): Promise<AxiosResponse<any>> =>
|
||||
request.post(`/container/container/${id}/stop`),
|
||||
containerStop: (id: string): any => http.Post(`/container/container/${id}/stop`),
|
||||
// 重启容器
|
||||
containerRestart: (id: string): Promise<AxiosResponse<any>> =>
|
||||
request.post(`/container/container/${id}/restart`),
|
||||
containerRestart: (id: string): any => http.Post(`/container/container/${id}/restart`),
|
||||
// 暂停容器
|
||||
containerPause: (id: string): Promise<AxiosResponse<any>> =>
|
||||
request.post(`/container/container/${id}/pause`),
|
||||
containerPause: (id: string): any => http.Post(`/container/container/${id}/pause`),
|
||||
// 恢复容器
|
||||
containerUnpause: (id: string): Promise<AxiosResponse<any>> =>
|
||||
request.post(`/container/container/${id}/unpause`),
|
||||
containerUnpause: (id: string): any => http.Post(`/container/container/${id}/unpause`),
|
||||
// 杀死容器
|
||||
containerKill: (id: string): Promise<AxiosResponse<any>> =>
|
||||
request.post(`/container/container/${id}/kill`),
|
||||
containerKill: (id: string): any => http.Post(`/container/container/${id}/kill`),
|
||||
// 重命名容器
|
||||
containerRename: (id: string, name: string): Promise<AxiosResponse<any>> =>
|
||||
request.post(`/container/container/${id}/rename`, { name }),
|
||||
containerRename: (id: string, name: string): any =>
|
||||
http.Post(`/container/container/${id}/rename`, { name }),
|
||||
// 获取容器日志
|
||||
containerLogs: (id: string): Promise<AxiosResponse<any>> =>
|
||||
request.get(`/container/container/${id}/logs`),
|
||||
containerLogs: (id: string): any => http.Get(`/container/container/${id}/logs`),
|
||||
// 清理容器
|
||||
containerPrune: (): Promise<AxiosResponse<any>> => request.post(`/container/container/prune`),
|
||||
containerPrune: (): any => http.Post(`/container/container/prune`),
|
||||
// 获取网络列表
|
||||
networkList: (page: number, limit: number): Promise<AxiosResponse<any>> =>
|
||||
request.get(`/container/network`, { params: { page, limit } }),
|
||||
networkList: (page: number, limit: number): any =>
|
||||
http.Get(`/container/network`, { params: { page, limit } }),
|
||||
// 创建网络
|
||||
networkCreate: (config: any): Promise<AxiosResponse<any>> =>
|
||||
request.post(`/container/network`, config),
|
||||
networkCreate: (config: any): any => http.Post(`/container/network`, config),
|
||||
// 删除网络
|
||||
networkRemove: (id: string): Promise<AxiosResponse<any>> =>
|
||||
request.delete(`/container/network/${id}`),
|
||||
networkRemove: (id: string): any => http.Delete(`/container/network/${id}`),
|
||||
// 清理网络
|
||||
networkPrune: (): Promise<AxiosResponse<any>> => request.post(`/container/network/prune`),
|
||||
networkPrune: (): any => http.Post(`/container/network/prune`),
|
||||
// 获取镜像列表
|
||||
imageList: (page: number, limit: number): Promise<AxiosResponse<any>> =>
|
||||
request.get(`/container/image`, { params: { page, limit } }),
|
||||
imageList: (page: number, limit: number): any =>
|
||||
http.Get(`/container/image`, { params: { page, limit } }),
|
||||
// 拉取镜像
|
||||
imagePull: (config: any): Promise<AxiosResponse<any>> => request.post(`/container/image`, config),
|
||||
imagePull: (config: any): any => http.Post(`/container/image`, config),
|
||||
// 删除镜像
|
||||
imageRemove: (id: string): Promise<AxiosResponse<any>> =>
|
||||
request.delete(`/container/image/${id}`),
|
||||
imageRemove: (id: string): any => http.Delete(`/container/image/${id}`),
|
||||
// 清理镜像
|
||||
imagePrune: (): Promise<AxiosResponse<any>> => request.post(`/container/image/prune`),
|
||||
imagePrune: (): any => http.Post(`/container/image/prune`),
|
||||
// 获取卷列表
|
||||
volumeList: (page: number, limit: number): Promise<AxiosResponse<any>> =>
|
||||
request.get(`/container/volume`, { params: { page, limit } }),
|
||||
volumeList: (page: number, limit: number): any =>
|
||||
http.Get(`/container/volume`, { params: { page, limit } }),
|
||||
// 创建卷
|
||||
volumeCreate: (config: any): Promise<AxiosResponse<any>> =>
|
||||
request.post(`/container/volume`, config),
|
||||
volumeCreate: (config: any): any => http.Post(`/container/volume`, config),
|
||||
// 删除卷
|
||||
volumeRemove: (id: string): Promise<AxiosResponse<any>> =>
|
||||
request.delete(`/container/volume/${id}`),
|
||||
volumeRemove: (id: string): any => http.Delete(`/container/volume/${id}`),
|
||||
// 清理卷
|
||||
volumePrune: (): Promise<AxiosResponse<any>> => request.post(`/container/volume/prune`)
|
||||
volumePrune: (): any => http.Post(`/container/volume/prune`)
|
||||
}
|
||||
|
||||
@@ -1,21 +1,17 @@
|
||||
import type { AxiosResponse } from 'axios'
|
||||
|
||||
import { request } from '@/utils'
|
||||
import { http } from '@/utils'
|
||||
|
||||
export default {
|
||||
// 获取任务列表
|
||||
list: (page: number, limit: number): Promise<AxiosResponse<any>> =>
|
||||
request.get('/cron', { params: { page, limit } }),
|
||||
list: (page: number, limit: number): any => http.Get('/cron', { params: { page, limit } }),
|
||||
// 获取任务脚本
|
||||
get: (id: number): Promise<AxiosResponse<any>> => request.get('/cron/' + id),
|
||||
get: (id: number): any => http.Get('/cron/' + id),
|
||||
// 创建任务
|
||||
create: (task: any): Promise<AxiosResponse<any>> => request.post('/cron', task),
|
||||
create: (task: any): any => http.Post('/cron', task),
|
||||
// 修改任务
|
||||
update: (id: number, name: string, time: string, script: string): Promise<AxiosResponse<any>> =>
|
||||
request.put('/cron/' + id, { name, time, script }),
|
||||
update: (id: number, name: string, time: string, script: string): any =>
|
||||
http.Put('/cron/' + id, { name, time, script }),
|
||||
// 删除任务
|
||||
delete: (id: number): Promise<AxiosResponse<any>> => request.delete('/cron/' + id),
|
||||
delete: (id: number): any => http.Delete(`/cron/${id}`),
|
||||
// 修改任务状态
|
||||
status: (id: number, status: boolean): Promise<AxiosResponse<any>> =>
|
||||
request.post('/cron/' + id + '/status', { status })
|
||||
status: (id: number, status: boolean): any => http.Post('/cron/' + id + '/status', { status })
|
||||
}
|
||||
|
||||
@@ -1,34 +1,25 @@
|
||||
import { http, request } from '@/utils'
|
||||
|
||||
import type { AxiosResponse } from 'axios'
|
||||
import type { RequestConfig } from '~/types/axios'
|
||||
import { http } from '@/utils'
|
||||
|
||||
export default {
|
||||
// 面板信息
|
||||
panel: (): Promise<Response> => fetch('/api/dashboard/panel'),
|
||||
// 面板菜单
|
||||
menu: (): Promise<AxiosResponse<any>> => request.get('/dashboard/menu'),
|
||||
panel: (): any => http.Get('/dashboard/panel'),
|
||||
// 首页应用
|
||||
homeApps: (): Promise<AxiosResponse<any>> => request.get('/dashboard/homeApps'),
|
||||
homeApps: (): any => http.Get('/dashboard/homeApps'),
|
||||
// 实时信息
|
||||
current: (nets: string[], disks: string[]): Promise<AxiosResponse<any>> =>
|
||||
request.post('/dashboard/current', { nets, disks }, { noNeedTip: true } as RequestConfig),
|
||||
current: (nets: string[], disks: string[]): any =>
|
||||
http.Post('/dashboard/current', { nets, disks }, { meta: { noAlert: true } }),
|
||||
// 系统信息
|
||||
systemInfo: (): Promise<AxiosResponse<any>> => request.get('/dashboard/systemInfo'),
|
||||
systemInfo: (): any => http.Get('/dashboard/systemInfo'),
|
||||
// 统计信息
|
||||
countInfo: (): Promise<AxiosResponse<any>> => request.get('/dashboard/countInfo'),
|
||||
countInfo: (): any => http.Get('/dashboard/countInfo'),
|
||||
// 已安装的数据库和PHP
|
||||
installedDbAndPhp: (): Promise<AxiosResponse<any>> => request.get('/dashboard/installedDbAndPhp'),
|
||||
installedDbAndPhp: (): any => http.Get('/dashboard/installedDbAndPhp'),
|
||||
// 检查更新
|
||||
checkUpdate: (): Promise<AxiosResponse<any>> => request.get('/dashboard/checkUpdate'),
|
||||
checkUpdate: (): any => http.Get('/dashboard/checkUpdate'),
|
||||
// 更新日志
|
||||
updateInfo: (): Promise<AxiosResponse<any>> => request.get('/dashboard/updateInfo'),
|
||||
updateInfo: (): any => http.Get('/dashboard/updateInfo'),
|
||||
// 更新面板
|
||||
update: (): Promise<AxiosResponse<any>> => request.post('/dashboard/update', null),
|
||||
update: (): any => http.Post('/dashboard/update'),
|
||||
// 重启面板
|
||||
restart: (): Promise<AxiosResponse<any>> => request.post('/dashboard/restart')
|
||||
restart: (): any => http.Post('/dashboard/restart')
|
||||
}
|
||||
|
||||
export const panel = () => http.Get('/dashboard/panel')
|
||||
export const current = (nets: string[], disks: string[]) =>
|
||||
http.Post('/dashboard/current', { nets, disks }, { meta: { noAlert: true } })
|
||||
|
||||
@@ -1,64 +1,39 @@
|
||||
import type { AxiosResponse } from 'axios'
|
||||
|
||||
import { request } from '@/utils'
|
||||
import { http } from '@/utils'
|
||||
|
||||
export default {
|
||||
// 创建文件/文件夹
|
||||
create: (path: string, dir: boolean): Promise<AxiosResponse<any>> =>
|
||||
request.post('/file/create', { path, dir }),
|
||||
create: (path: string, dir: boolean): any => http.Post('/file/create', { path, dir }),
|
||||
// 获取文件内容
|
||||
content: (path: string): Promise<AxiosResponse<any>> =>
|
||||
request.get('/file/content', { params: { path } }),
|
||||
content: (path: string): any => http.Get('/file/content', { params: { path } }),
|
||||
// 保存文件
|
||||
save: (path: string, content: string): Promise<AxiosResponse<any>> =>
|
||||
request.post('/file/save', { path, content }),
|
||||
save: (path: string, content: string): any => http.Post('/file/save', { path, content }),
|
||||
// 删除文件
|
||||
delete: (path: string): Promise<AxiosResponse<any>> => request.post('/file/delete', { path }),
|
||||
delete: (path: string): any => http.Post('/file/delete', { path }),
|
||||
// 上传文件
|
||||
upload: (path: string, formData: FormData, onProgress: any): Promise<AxiosResponse<any>> => {
|
||||
formData.append('path', path)
|
||||
return request.post('/file/upload', formData, {
|
||||
headers: { 'Content-Type': 'multipart/form-data' },
|
||||
onUploadProgress: (progressEvent: any) => {
|
||||
onProgress({ percent: Math.ceil((progressEvent.loaded / progressEvent.total) * 100) })
|
||||
}
|
||||
})
|
||||
},
|
||||
upload: (formData: FormData): any => http.Post('/file/upload', formData),
|
||||
// 检查文件是否存在
|
||||
exist: (paths: string[]): Promise<AxiosResponse<any>> => request.post('/file/exist', paths),
|
||||
exist: (paths: string[]): any => http.Post('/file/exist', paths),
|
||||
// 移动文件
|
||||
move: (paths: any[]): Promise<AxiosResponse<any>> => request.post('/file/move', paths),
|
||||
move: (paths: any[]): any => http.Post('/file/move', paths),
|
||||
// 复制文件
|
||||
copy: (paths: any[]): Promise<AxiosResponse<any>> => request.post('/file/copy', paths),
|
||||
copy: (paths: any[]): any => http.Post('/file/copy', paths),
|
||||
// 远程下载
|
||||
remoteDownload: (path: string, url: string): Promise<AxiosResponse<any>> =>
|
||||
request.post('/file/remoteDownload', { path, url }),
|
||||
remoteDownload: (path: string, url: string): any =>
|
||||
http.Post('/file/remoteDownload', { path, url }),
|
||||
// 获取文件信息
|
||||
info: (path: string): Promise<AxiosResponse<any>> =>
|
||||
request.get('/file/info', { params: { path } }),
|
||||
info: (path: string): any => http.Get('/file/info', { params: { path } }),
|
||||
// 修改文件权限
|
||||
permission: (
|
||||
path: string,
|
||||
mode: string,
|
||||
owner: string,
|
||||
group: string
|
||||
): Promise<AxiosResponse<any>> => request.post('/file/permission', { path, mode, owner, group }),
|
||||
permission: (path: string, mode: string, owner: string, group: string): any =>
|
||||
http.Post('/file/permission', { path, mode, owner, group }),
|
||||
// 压缩文件
|
||||
compress: (dir: string, paths: string[], file: string): Promise<AxiosResponse<any>> =>
|
||||
request.post('/file/compress', { dir, paths, file }),
|
||||
compress: (dir: string, paths: string[], file: string): any =>
|
||||
http.Post('/file/compress', { dir, paths, file }),
|
||||
// 解压文件
|
||||
unCompress: (file: string, path: string): Promise<AxiosResponse<any>> =>
|
||||
request.post('/file/unCompress', { file, path }),
|
||||
unCompress: (file: string, path: string): any => http.Post('/file/unCompress', { file, path }),
|
||||
// 搜索文件
|
||||
search: (
|
||||
path: string,
|
||||
keyword: string,
|
||||
sub: boolean,
|
||||
page: number,
|
||||
limit: number
|
||||
): Promise<AxiosResponse<any>> =>
|
||||
request.get('/file/search', { params: { path, keyword, sub, page, limit } }),
|
||||
search: (path: string, keyword: string, sub: boolean, page: number, limit: number): any =>
|
||||
http.Get('/file/search', { params: { path, keyword, sub, page, limit } }),
|
||||
// 获取文件列表
|
||||
list: (path: string, page: number, limit: number, sort: string): Promise<AxiosResponse<any>> =>
|
||||
request.get('/file/list', { params: { path, page, limit, sort } })
|
||||
list: (path: string, page: number, limit: number, sort: string): any =>
|
||||
http.Get('/file/list', { params: { path, page, limit, sort } })
|
||||
}
|
||||
|
||||
@@ -1,36 +1,29 @@
|
||||
import type { AxiosResponse } from 'axios'
|
||||
|
||||
import { request } from '@/utils'
|
||||
import { http } from '@/utils'
|
||||
|
||||
export default {
|
||||
// 获取防火墙状态
|
||||
status: (): Promise<AxiosResponse<any>> => request.get('/firewall/status'),
|
||||
status: (): any => http.Get('/firewall/status'),
|
||||
// 设置防火墙状态
|
||||
updateStatus: (status: boolean): Promise<AxiosResponse<any>> =>
|
||||
request.post('/firewall/status', { status }),
|
||||
updateStatus: (status: boolean): any => http.Post('/firewall/status', { status }),
|
||||
// 获取防火墙规则
|
||||
rules: (page: number, limit: number): Promise<AxiosResponse<any>> =>
|
||||
request.get('/firewall/rule', { params: { page, limit } }),
|
||||
rules: (page: number, limit: number): any =>
|
||||
http.Get('/firewall/rule', { params: { page, limit } }),
|
||||
// 创建防火墙规则
|
||||
createRule: (rule: any): Promise<AxiosResponse<any>> => request.post('/firewall/rule', rule),
|
||||
createRule: (rule: any): any => http.Post('/firewall/rule', rule),
|
||||
// 删除防火墙规则
|
||||
deleteRule: (rule: any): Promise<AxiosResponse<any>> =>
|
||||
request.delete('/firewall/rule', { data: rule }),
|
||||
deleteRule: (rule: any): any => http.Delete('/firewall/rule', rule),
|
||||
// 获取防火墙IP规则
|
||||
ipRules: (page: number, limit: number): Promise<AxiosResponse<any>> =>
|
||||
request.get('/firewall/ipRule', { params: { page, limit } }),
|
||||
ipRules: (page: number, limit: number): any =>
|
||||
http.Get('/firewall/ipRule', { params: { page, limit } }),
|
||||
// 创建防火墙IP规则
|
||||
createIpRule: (rule: any): Promise<AxiosResponse<any>> => request.post('/firewall/ipRule', rule),
|
||||
createIpRule: (rule: any): any => http.Post('/firewall/ipRule', rule),
|
||||
// 删除防火墙IP规则
|
||||
deleteIpRule: (rule: any): Promise<AxiosResponse<any>> =>
|
||||
request.delete('/firewall/ipRule', { data: rule }),
|
||||
deleteIpRule: (rule: any): any => http.Delete('/firewall/ipRule', rule),
|
||||
// 获取防火墙转发规则
|
||||
forwards: (page: number, limit: number): Promise<AxiosResponse<any>> =>
|
||||
request.get('/firewall/forward', { params: { page, limit } }),
|
||||
forwards: (page: number, limit: number): any =>
|
||||
http.Get('/firewall/forward', { params: { page, limit } }),
|
||||
// 创建防火墙转发规则
|
||||
createForward: (rule: any): Promise<AxiosResponse<any>> =>
|
||||
request.post('/firewall/forward', rule),
|
||||
createForward: (rule: any): any => http.Post('/firewall/forward', rule),
|
||||
// 删除防火墙转发规则
|
||||
deleteForward: (rule: any): Promise<AxiosResponse<any>> =>
|
||||
request.delete('/firewall/forward', { data: rule })
|
||||
deleteForward: (rule: any): any => http.Delete('/firewall/forward', rule)
|
||||
}
|
||||
|
||||
@@ -1,16 +1,13 @@
|
||||
import type { AxiosResponse } from 'axios'
|
||||
|
||||
import { request } from '@/utils'
|
||||
import { http } from '@/utils'
|
||||
|
||||
export default {
|
||||
// 开关
|
||||
setting: (): Promise<AxiosResponse<any>> => request.get('/monitor/setting'),
|
||||
setting: (): any => http.Get('/monitor/setting'),
|
||||
// 保存天数
|
||||
updateSetting: (enabled: boolean, days: number): Promise<AxiosResponse<any>> =>
|
||||
request.post('/monitor/setting', { enabled, days }),
|
||||
updateSetting: (enabled: boolean, days: number): any =>
|
||||
http.Post('/monitor/setting', { enabled, days }),
|
||||
// 清空监控记录
|
||||
clear: (): Promise<AxiosResponse<any>> => request.post('/monitor/clear'),
|
||||
clear: (): any => http.Post('/monitor/clear'),
|
||||
// 监控记录
|
||||
list: (start: number, end: number): Promise<AxiosResponse<any>> =>
|
||||
request.get('/monitor/list', { params: { start, end } })
|
||||
list: (start: number, end: number): any => http.Get('/monitor/list', { params: { start, end } })
|
||||
}
|
||||
|
||||
@@ -1,16 +1,8 @@
|
||||
import type { AxiosResponse } from 'axios'
|
||||
|
||||
import { request } from '@/utils'
|
||||
import { http } from '@/utils'
|
||||
|
||||
export default {
|
||||
// 获取SSH
|
||||
ssh: (): Promise<AxiosResponse<any>> => request.get('/safe/ssh'),
|
||||
// 设置SSH
|
||||
setSsh: (status: boolean, port: number): Promise<AxiosResponse<any>> =>
|
||||
request.post('/safe/ssh', { status, port }),
|
||||
// 获取Ping状态
|
||||
pingStatus: (): Promise<AxiosResponse<any>> => request.get('/safe/ping'),
|
||||
// 设置Ping状态
|
||||
setPingStatus: (status: boolean): Promise<AxiosResponse<any>> =>
|
||||
request.post('/safe/ping', { status })
|
||||
ssh: (): any => http.Get('/safe/ssh'),
|
||||
updateSsh: (status: boolean, port: number): any => http.Post('/safe/ssh', { status, port }),
|
||||
pingStatus: (): any => http.Get('/safe/ping'),
|
||||
updatePingStatus: (status: boolean): any => http.Post('/safe/ping', { status })
|
||||
}
|
||||
|
||||
@@ -1,14 +1,8 @@
|
||||
import type { AxiosResponse } from 'axios'
|
||||
|
||||
import { request } from '@/utils'
|
||||
import { http } from '@/utils'
|
||||
|
||||
export default {
|
||||
// 获取设置
|
||||
list: (): Promise<AxiosResponse<any>> => request.get('/setting'),
|
||||
list: (): any => http.Get('/setting'),
|
||||
// 保存设置
|
||||
update: (settings: any): Promise<AxiosResponse<any>> => request.post('/setting', settings),
|
||||
// 获取HTTPS设置
|
||||
getHttps: (): Promise<AxiosResponse<any>> => request.get('/setting/https'),
|
||||
// 保存HTTPS设置
|
||||
updateHttps: (https: any): Promise<AxiosResponse<any>> => request.post('/setting/https', https)
|
||||
update: (settings: any): any => http.Post('/setting', settings)
|
||||
}
|
||||
|
||||
@@ -1,17 +1,14 @@
|
||||
import type { AxiosResponse } from 'axios'
|
||||
|
||||
import { request } from '@/utils'
|
||||
import { http } from '@/utils'
|
||||
|
||||
export default {
|
||||
// 获取主机列表
|
||||
list: (page: number, limit: number): Promise<AxiosResponse<any>> =>
|
||||
request.get('/ssh', { params: { page, limit } }),
|
||||
list: (page: number, limit: number): any => http.Get('/ssh', { params: { page, limit } }),
|
||||
// 获取主机信息
|
||||
get: (id: number): Promise<AxiosResponse<any>> => request.get(`/ssh/${id}`),
|
||||
get: (id: number): any => http.Get(`/ssh/${id}`),
|
||||
// 创建主机
|
||||
create: (req: any): Promise<AxiosResponse<any>> => request.post('/ssh', req),
|
||||
create: (req: any): any => http.Post('/ssh', req),
|
||||
// 修改主机
|
||||
update: (id: number, req: any): Promise<AxiosResponse<any>> => request.put(`/ssh/${id}`, req),
|
||||
update: (id: number, req: any): any => http.Put(`/ssh/${id}`, req),
|
||||
// 删除主机
|
||||
delete: (id: number): Promise<AxiosResponse<any>> => request.delete(`/ssh/${id}`)
|
||||
delete: (id: number): any => http.Delete(`/ssh/${id}`)
|
||||
}
|
||||
|
||||
@@ -1,30 +1,20 @@
|
||||
import type { AxiosResponse } from 'axios'
|
||||
|
||||
import { request } from '@/utils'
|
||||
import { http } from '@/utils'
|
||||
|
||||
export default {
|
||||
// 服务状态
|
||||
status: (service: string): Promise<AxiosResponse<any>> =>
|
||||
request.get('/systemctl/status', { params: { service } }),
|
||||
status: (service: string): any => http.Get('/systemctl/status', { params: { service } }),
|
||||
// 是否启用服务
|
||||
isEnabled: (service: string): Promise<AxiosResponse<any>> =>
|
||||
request.get('/systemctl/isEnabled', { params: { service } }),
|
||||
isEnabled: (service: string): any => http.Get('/systemctl/isEnabled', { params: { service } }),
|
||||
// 启用服务
|
||||
enable: (service: string): Promise<AxiosResponse<any>> =>
|
||||
request.post('/systemctl/enable', { service }),
|
||||
enable: (service: string): any => http.Post('/systemctl/enable', { service }),
|
||||
// 禁用服务
|
||||
disable: (service: string): Promise<AxiosResponse<any>> =>
|
||||
request.post('/systemctl/disable', { service }),
|
||||
disable: (service: string): any => http.Post('/systemctl/disable', { service }),
|
||||
// 重启服务
|
||||
restart: (service: string): Promise<AxiosResponse<any>> =>
|
||||
request.post('/systemctl/restart', { service }),
|
||||
restart: (service: string): any => http.Post('/systemctl/restart', { service }),
|
||||
// 重载服务
|
||||
reload: (service: string): Promise<AxiosResponse<any>> =>
|
||||
request.post('/systemctl/reload', { service }),
|
||||
reload: (service: string): any => http.Post('/systemctl/reload', { service }),
|
||||
// 启动服务
|
||||
start: (service: string): Promise<AxiosResponse<any>> =>
|
||||
request.post('/systemctl/start', { service }),
|
||||
start: (service: string): any => http.Post('/systemctl/start', { service }),
|
||||
// 停止服务
|
||||
stop: (service: string): Promise<AxiosResponse<any>> =>
|
||||
request.post('/systemctl/stop', { service })
|
||||
stop: (service: string): any => http.Post('/systemctl/stop', { service })
|
||||
}
|
||||
|
||||
@@ -1,15 +1,12 @@
|
||||
import type { AxiosResponse } from 'axios'
|
||||
|
||||
import { request } from '@/utils'
|
||||
import { http } from '@/utils'
|
||||
|
||||
export default {
|
||||
// 获取状态
|
||||
status: (): Promise<AxiosResponse<any>> => request.get('/task/status'),
|
||||
status: (): any => http.Get('/task/status'),
|
||||
// 获取任务列表
|
||||
list: (page: number, limit: number): Promise<AxiosResponse<any>> =>
|
||||
request.get('/task', { params: { page, limit } }),
|
||||
list: (page: number, limit: number): any => http.Get('/task', { params: { page, limit } }),
|
||||
// 获取任务
|
||||
get: (id: number): Promise<AxiosResponse<any>> => request.get('/task/' + id),
|
||||
get: (id: number): any => http.Get(`/task/${id}`),
|
||||
// 删除任务
|
||||
delete: (id: number): Promise<AxiosResponse<any>> => request.delete('/task/' + id)
|
||||
delete: (id: number): any => http.Delete(`/task/${id}`)
|
||||
}
|
||||
|
||||
@@ -1,39 +1,33 @@
|
||||
import type { AxiosResponse } from 'axios'
|
||||
|
||||
import { http, request } from '@/utils'
|
||||
import { http } from '@/utils'
|
||||
|
||||
export default {
|
||||
// 列表
|
||||
list: (page: number, limit: number): Promise<AxiosResponse<any>> =>
|
||||
request.get('/website', { params: { page, limit } }),
|
||||
list: (page: number, limit: number): any => http.Get('/website', { params: { page, limit } }),
|
||||
// 创建
|
||||
create: (data: any): Promise<AxiosResponse<any>> => request.post('/website', data),
|
||||
create: (data: any): any => http.Post('/website', data),
|
||||
// 删除
|
||||
delete: (id: number, path: boolean, db: boolean): Promise<AxiosResponse<any>> =>
|
||||
request.delete(`/website/${id}`, { data: { path, db } }),
|
||||
delete: (id: number, path: boolean, db: boolean): any =>
|
||||
http.Delete(`/website/${id}`, { path, db }),
|
||||
// 伪静态
|
||||
rewrites: () => http.Get(`/website/rewrites`),
|
||||
rewrites: (): any => http.Get(`/website/rewrites`),
|
||||
// 获取默认配置
|
||||
defaultConfig: (): Promise<AxiosResponse<any>> => request.get('/website/defaultConfig'),
|
||||
defaultConfig: (): any => http.Get('/website/defaultConfig'),
|
||||
// 保存默认配置
|
||||
saveDefaultConfig: (index: string, stop: string): Promise<AxiosResponse<any>> =>
|
||||
request.post('/website/defaultConfig', { index, stop }),
|
||||
saveDefaultConfig: (index: string, stop: string): any =>
|
||||
http.Post('/website/defaultConfig', { index, stop }),
|
||||
// 网站配置
|
||||
config: (id: number): Promise<AxiosResponse<any>> => request.get('/website/' + id),
|
||||
config: (id: number): any => http.Get('/website/' + id),
|
||||
// 保存网站配置
|
||||
saveConfig: (id: number, data: any): Promise<AxiosResponse<any>> =>
|
||||
request.put(`/website/${id}`, data),
|
||||
saveConfig: (id: number, data: any): any => http.Put(`/website/${id}`, data),
|
||||
// 清空日志
|
||||
clearLog: (id: number): Promise<AxiosResponse<any>> => request.delete('/website/' + id + '/log'),
|
||||
clearLog: (id: number): any => http.Delete('/website/' + id + '/log'),
|
||||
// 更新备注
|
||||
updateRemark: (id: number, remark: string): Promise<AxiosResponse<any>> =>
|
||||
request.post(`/website/${id}` + '/updateRemark', { remark }),
|
||||
updateRemark: (id: number, remark: string): any =>
|
||||
http.Post(`/website/${id}` + '/updateRemark', { remark }),
|
||||
// 重置配置
|
||||
resetConfig: (id: number): Promise<AxiosResponse<any>> =>
|
||||
request.post(`/website/${id}/resetConfig`),
|
||||
resetConfig: (id: number): any => http.Post(`/website/${id}/resetConfig`),
|
||||
// 修改状态
|
||||
status: (id: number, status: boolean): Promise<AxiosResponse<any>> =>
|
||||
request.post(`/website/${id}/status`, { status }),
|
||||
status: (id: number, status: boolean): any => http.Post(`/website/${id}/status`, { status }),
|
||||
// 签发证书
|
||||
obtainCert: (id: number): Promise<AxiosResponse<any>> => request.post(`/website/${id}/obtainCert`)
|
||||
obtainCert: (id: number): any => http.Post(`/website/${id}/obtainCert`)
|
||||
}
|
||||
|
||||
@@ -2,11 +2,7 @@
|
||||
<footer color="#6a6a6a" f-c-c flex-col text-14>
|
||||
<p>
|
||||
© 2022 - {{ year }}
|
||||
<a
|
||||
hover="decoration-primary color-primary"
|
||||
target="__blank"
|
||||
href="https://github.com/tnb-labs/panel"
|
||||
>
|
||||
<a hover="decoration-primary color-primary" target="__blank" href="https://panel.haozi.net/">
|
||||
耗子面板
|
||||
</a>
|
||||
All Rights Reserved.
|
||||
@@ -20,14 +16,18 @@
|
||||
Q群 12370907
|
||||
</a>
|
||||
<n-divider vertical />
|
||||
<a hover="decoration-primary color-primary" target="_blank" href="https://bbs.haozi.net/docs">
|
||||
<a
|
||||
hover="decoration-primary color-primary"
|
||||
target="_blank"
|
||||
href="https://panel.haozi.net/docs"
|
||||
>
|
||||
使用文档
|
||||
</a>
|
||||
<n-divider vertical />
|
||||
<a
|
||||
hover="decoration-primary color-primary"
|
||||
target="_blank"
|
||||
href="https://bbs.haozi.net/c/technical/panel"
|
||||
href="https://tom.moe/c/technical/panel"
|
||||
>
|
||||
交流社区
|
||||
</a>
|
||||
|
||||
@@ -16,27 +16,27 @@ const props = defineProps({
|
||||
})
|
||||
|
||||
const disabled = ref(false) // 在出现错误的情况下禁用保存
|
||||
const data = ref('')
|
||||
const content = ref('')
|
||||
|
||||
const get = async () => {
|
||||
await file
|
||||
.content(props.path)
|
||||
.then((res) => {
|
||||
data.value = decodeBase64(res.data.content)
|
||||
const get = () => {
|
||||
useRequest(file.content(props.path))
|
||||
.onSuccess(({ data }) => {
|
||||
content.value = decodeBase64(data.content)
|
||||
window.$message.success('获取成功')
|
||||
})
|
||||
.catch(() => {
|
||||
.onError(() => {
|
||||
disabled.value = true
|
||||
})
|
||||
}
|
||||
|
||||
const save = async () => {
|
||||
const save = () => {
|
||||
if (disabled.value) {
|
||||
window.$message.error('当前状态下不可保存')
|
||||
return
|
||||
}
|
||||
await file.save(props.path, data.value)
|
||||
window.$message.success('保存成功')
|
||||
useRequest(file.save(props.path, content.value)).onSuccess(() => {
|
||||
window.$message.success('保存成功')
|
||||
})
|
||||
}
|
||||
|
||||
onMounted(() => {
|
||||
@@ -51,7 +51,7 @@ defineExpose({
|
||||
|
||||
<template>
|
||||
<Editor
|
||||
v-model:value="data"
|
||||
v-model:value="content"
|
||||
:language="languageByPath(props.path)"
|
||||
theme="vs-dark"
|
||||
height="60vh"
|
||||
|
||||
@@ -0,0 +1,336 @@
|
||||
<script setup lang="ts">
|
||||
import file from '@/api/panel/file'
|
||||
import TheIcon from '@/components/custom/TheIcon.vue'
|
||||
import { checkName, checkPath, getExt, getIconByExt } from '@/utils'
|
||||
import type { DataTableColumns, InputInst } from 'naive-ui'
|
||||
import { NButton, NDataTable, NEllipsis, NFlex, NTag } from 'naive-ui'
|
||||
import type { RowData } from 'naive-ui/es/data-table/src/interface'
|
||||
|
||||
const show = defineModel<boolean>('show', { type: Boolean, required: true })
|
||||
const path = defineModel<string>('path', { type: String, required: true })
|
||||
const props = defineProps({
|
||||
dir: {
|
||||
type: Boolean,
|
||||
required: true
|
||||
}
|
||||
})
|
||||
|
||||
const title = computed(() => (props.dir ? '选择目录' : '选择文件'))
|
||||
const isInput = ref(false)
|
||||
const pathInput = ref<InputInst | null>(null)
|
||||
const input = ref('www')
|
||||
const sort = ref<string>('')
|
||||
const selected = defineModel<any[]>('selected', { type: Array, default: () => [] })
|
||||
const create = ref(false)
|
||||
const createModel = ref({
|
||||
dir: false,
|
||||
path: ''
|
||||
})
|
||||
|
||||
const columns: DataTableColumns<RowData> = [
|
||||
{
|
||||
type: 'selection',
|
||||
multiple: false,
|
||||
fixed: 'left',
|
||||
disabled(row) {
|
||||
return props.dir ? !row.dir : row.dir
|
||||
}
|
||||
},
|
||||
{
|
||||
title: '名称',
|
||||
key: 'name',
|
||||
minWidth: 180,
|
||||
defaultSortOrder: false,
|
||||
sorter: 'default',
|
||||
render(row) {
|
||||
let icon = 'bi:file-earmark'
|
||||
if (row.dir) {
|
||||
icon = 'bi:folder'
|
||||
} else {
|
||||
icon = getIconByExt(getExt(row.name))
|
||||
}
|
||||
|
||||
return h(
|
||||
NFlex,
|
||||
{
|
||||
class: 'cursor-pointer hover:opacity-60',
|
||||
onClick: () => {
|
||||
if (row.dir) {
|
||||
path.value = row.full
|
||||
} else {
|
||||
selected.value = [row.full]
|
||||
}
|
||||
}
|
||||
},
|
||||
() => [
|
||||
h(TheIcon, { icon, size: 24, color: `var(--primary-color)` }),
|
||||
h(NEllipsis, null, {
|
||||
default: () => {
|
||||
if (row.symlink) {
|
||||
return row.name + ' -> ' + row.link
|
||||
} else {
|
||||
return row.name
|
||||
}
|
||||
}
|
||||
})
|
||||
]
|
||||
)
|
||||
}
|
||||
},
|
||||
{
|
||||
title: '权限',
|
||||
key: 'mode',
|
||||
minWidth: 80,
|
||||
render(row: any): any {
|
||||
return h(
|
||||
NTag,
|
||||
{ type: 'success', size: 'small', bordered: false },
|
||||
{ default: () => row.mode }
|
||||
)
|
||||
}
|
||||
},
|
||||
{
|
||||
title: '所有者 / 组',
|
||||
key: 'owner/group',
|
||||
minWidth: 120,
|
||||
render(row: any): any {
|
||||
return h('div', null, [
|
||||
h(NTag, { type: 'primary', size: 'small', bordered: false }, { default: () => row.owner }),
|
||||
' / ',
|
||||
h(NTag, { type: 'primary', size: 'small', bordered: false }, { default: () => row.group })
|
||||
])
|
||||
}
|
||||
},
|
||||
{
|
||||
title: '大小',
|
||||
key: 'size',
|
||||
minWidth: 80,
|
||||
render(row: any): any {
|
||||
return h(NTag, { type: 'info', size: 'small', bordered: false }, { default: () => row.size })
|
||||
}
|
||||
},
|
||||
{
|
||||
title: '修改时间',
|
||||
key: 'modify',
|
||||
minWidth: 200,
|
||||
render(row: any): any {
|
||||
return h(
|
||||
NTag,
|
||||
{ type: 'warning', size: 'small', bordered: false },
|
||||
{ default: () => row.modify }
|
||||
)
|
||||
}
|
||||
}
|
||||
]
|
||||
|
||||
const { loading, data, page, total, pageSize, pageCount, refresh } = usePagination(
|
||||
(page, pageSize) => file.list(path.value, page, pageSize, sort.value),
|
||||
{
|
||||
initialData: { total: 0, list: [] },
|
||||
initialPageSize: 100,
|
||||
total: (res: any) => res.total,
|
||||
data: (res: any) => res.items
|
||||
}
|
||||
)
|
||||
|
||||
const handleInput = () => {
|
||||
isInput.value = true
|
||||
nextTick(() => {
|
||||
pathInput.value?.focus()
|
||||
})
|
||||
}
|
||||
|
||||
const handleBlur = () => {
|
||||
input.value = input.value.replace(/(^\/)|(\/$)/g, '')
|
||||
if (!checkPath(input.value)) {
|
||||
window.$message.error('路径不合法')
|
||||
return
|
||||
}
|
||||
|
||||
isInput.value = false
|
||||
path.value = '/' + input.value
|
||||
}
|
||||
|
||||
const handleUp = () => {
|
||||
const count = splitPath(path.value, '/').length
|
||||
setPath(count - 2)
|
||||
}
|
||||
|
||||
const splitPath = (str: string, delimiter: string) => {
|
||||
if (str === delimiter || str === '') {
|
||||
return []
|
||||
}
|
||||
return str.split(delimiter).slice(1)
|
||||
}
|
||||
|
||||
const setPath = (index: number) => {
|
||||
const newPath = splitPath(path.value, '/')
|
||||
.slice(0, index + 1)
|
||||
.join('/')
|
||||
path.value = '/' + newPath
|
||||
input.value = newPath
|
||||
}
|
||||
|
||||
const handleSorterChange = (sorter: {
|
||||
columnKey: string | number | null
|
||||
order: 'ascend' | 'descend' | false
|
||||
}) => {
|
||||
if (!sorter || sorter.columnKey === 'name') {
|
||||
if (!loading.value) {
|
||||
switch (sorter.order) {
|
||||
case 'ascend':
|
||||
sort.value = 'asc'
|
||||
refresh()
|
||||
break
|
||||
case 'descend':
|
||||
sort.value = 'desc'
|
||||
refresh()
|
||||
break
|
||||
default:
|
||||
sort.value = ''
|
||||
refresh()
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const showCreate = (value: string) => {
|
||||
createModel.value.dir = value !== 'file'
|
||||
createModel.value.path = ''
|
||||
create.value = true
|
||||
}
|
||||
|
||||
const handleCreate = () => {
|
||||
if (!checkName(createModel.value.path)) {
|
||||
window.$message.error('名称不合法')
|
||||
return
|
||||
}
|
||||
|
||||
const fullPath = path.value + '/' + createModel.value.path
|
||||
useRequest(file.create(fullPath, createModel.value.dir)).onSuccess(() => {
|
||||
create.value = false
|
||||
refresh()
|
||||
window.$message.success('新建成功')
|
||||
})
|
||||
}
|
||||
|
||||
const closeWatch = watch(
|
||||
path,
|
||||
(value) => {
|
||||
input.value = value.slice(1)
|
||||
selected.value = []
|
||||
refresh()
|
||||
},
|
||||
{ immediate: true }
|
||||
)
|
||||
|
||||
const handleClose = () => {
|
||||
closeWatch()
|
||||
if (selected.value.length) {
|
||||
path.value = selected.value[0]
|
||||
selected.value = []
|
||||
}
|
||||
show.value = false
|
||||
}
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<n-modal
|
||||
v-model:show="show"
|
||||
preset="card"
|
||||
:title="title"
|
||||
style="width: 60vw"
|
||||
size="huge"
|
||||
:bordered="false"
|
||||
:segmented="false"
|
||||
@close="handleClose"
|
||||
@mask-click="handleClose"
|
||||
>
|
||||
<n-flex>
|
||||
<n-popselect
|
||||
:options="[
|
||||
{ label: '文件', value: 'file' },
|
||||
{ label: '文件夹', value: 'folder' }
|
||||
]"
|
||||
@update:value="showCreate"
|
||||
>
|
||||
<n-button type="primary"> 新建 </n-button>
|
||||
</n-popselect>
|
||||
<n-button @click="handleUp">
|
||||
<icon-bi-arrow-up />
|
||||
</n-button>
|
||||
<n-input-group flex-1>
|
||||
<n-tag size="large" v-if="!isInput" flex-1 @click="handleInput">
|
||||
<n-breadcrumb separator=">">
|
||||
<n-breadcrumb-item @click.stop="setPath(-1)"> 根目录 </n-breadcrumb-item>
|
||||
<n-breadcrumb-item
|
||||
v-for="(item, index) in splitPath(path, '/')"
|
||||
:key="index"
|
||||
@click.stop="setPath(index)"
|
||||
>
|
||||
{{ item }}
|
||||
</n-breadcrumb-item>
|
||||
</n-breadcrumb>
|
||||
</n-tag>
|
||||
<n-input-group-label v-if="isInput">/</n-input-group-label>
|
||||
<n-input
|
||||
ref="pathInput"
|
||||
v-model:value="input"
|
||||
v-if="isInput"
|
||||
@keyup.enter="handleBlur"
|
||||
@blur="handleBlur"
|
||||
/>
|
||||
</n-input-group>
|
||||
<n-button @click="refresh">
|
||||
<icon-bi-arrow-clockwise />
|
||||
</n-button>
|
||||
</n-flex>
|
||||
<n-data-table
|
||||
remote
|
||||
striped
|
||||
virtual-scroll
|
||||
pt-20
|
||||
size="small"
|
||||
:scroll-x="600"
|
||||
:columns="columns"
|
||||
:data="data"
|
||||
:loading="loading"
|
||||
:row-key="(row: any) => row.full"
|
||||
max-height="60vh"
|
||||
@update:sorter="handleSorterChange"
|
||||
v-model:checked-row-keys="selected"
|
||||
v-model:page="page"
|
||||
v-model:pageSize="pageSize"
|
||||
:pagination="{
|
||||
page: page,
|
||||
pageCount: pageCount,
|
||||
pageSize: pageSize,
|
||||
itemCount: total,
|
||||
showQuickJumper: true,
|
||||
showSizePicker: true,
|
||||
pageSizes: [100, 200, 500, 1000, 1500, 2000, 5000]
|
||||
}"
|
||||
/>
|
||||
</n-modal>
|
||||
<n-modal
|
||||
v-model:show="create"
|
||||
preset="card"
|
||||
title="新建"
|
||||
style="width: 60vw"
|
||||
size="huge"
|
||||
:bordered="false"
|
||||
:segmented="false"
|
||||
>
|
||||
<n-space vertical>
|
||||
<n-form :model="createModel">
|
||||
<n-form-item label="名称">
|
||||
<n-input v-model:value="createModel.path" />
|
||||
</n-form-item>
|
||||
</n-form>
|
||||
<n-button type="info" block @click="handleCreate">提交</n-button>
|
||||
</n-space>
|
||||
</n-modal>
|
||||
</template>
|
||||
|
||||
<style scoped lang="scss"></style>
|
||||
@@ -12,7 +12,7 @@ withDefaults(defineProps<Props>(), {
|
||||
<transition appear mode="out-in" name="fade-slide">
|
||||
<section class="cus-scroll-y wh-full flex-col bg-[#f5f6fb] p-15" dark:bg-hex-121212>
|
||||
<slot />
|
||||
<AppFooter v-if="showFooter" mt-15 />
|
||||
<app-footer v-if="showFooter" mt-15 />
|
||||
</section>
|
||||
</transition>
|
||||
</template>
|
||||
|
||||
@@ -19,7 +19,7 @@ const route = useRoute()
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<AppPage :show-footer="showFooter">
|
||||
<app-page :show-footer="showFooter">
|
||||
<header v-if="showHeader" mb-15 min-h-45 flex items-center justify-between px-15>
|
||||
<slot v-if="$slots.header" name="header" />
|
||||
<template v-else>
|
||||
@@ -33,8 +33,8 @@ const route = useRoute()
|
||||
</template>
|
||||
</header>
|
||||
|
||||
<n-card flex-1 rounded-10>
|
||||
<n-card flex-1>
|
||||
<slot />
|
||||
</n-card>
|
||||
</AppPage>
|
||||
</app-page>
|
||||
</template>
|
||||
|
||||
@@ -41,9 +41,9 @@
|
||||
"cache": "缓存更新成功",
|
||||
"warning": "更新应用前强烈建议先备份/快照,以免出现问题时无法第一时间回滚!",
|
||||
"setup": "设置成功",
|
||||
"install": "任务已提交,请前往后台任务查看任务进度",
|
||||
"update": "任务已提交,请前往后台任务查看任务进度",
|
||||
"uninstall": "任务已提交,请前往后台任务查看任务进度"
|
||||
"install": "任务已提交,请前往后台任务查看进度",
|
||||
"update": "任务已提交,请前往后台任务查看进度",
|
||||
"uninstall": "任务已提交,请前往后台任务查看进度"
|
||||
},
|
||||
"buttons": {
|
||||
"updateCache": "更新缓存",
|
||||
|
||||
@@ -14,17 +14,17 @@ const themeStore = useThemeStore()
|
||||
|
||||
<template>
|
||||
<div w-full flex items-center justify-between>
|
||||
<MenuCollapse v-if="themeStore.isMobile" />
|
||||
<menu-collapse v-if="themeStore.isMobile" />
|
||||
<section v-if="!themeStore.isMobile && themeStore.tab.visible" w-0 flex-1 pr-12>
|
||||
<AppTab />
|
||||
<app-tab />
|
||||
</section>
|
||||
<span v-if="!themeStore.isMobile && themeStore.tab.visible" mx-6 opacity-20>|</span>
|
||||
<div ml-auto flex flex-shrink-0 items-center px-12>
|
||||
<ReloadPage />
|
||||
<FullScreen />
|
||||
<ThemeMode />
|
||||
<ThemeSetting />
|
||||
<UserAvatar />
|
||||
<reload-page />
|
||||
<full-screen />
|
||||
<theme-mode />
|
||||
<theme-setting />
|
||||
<user-avatar />
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
+3
-3
@@ -13,14 +13,14 @@ import { setupNaiveDiscreteApi } from './utils'
|
||||
|
||||
import { install as VueMonacoEditorPlugin } from '@guolao/vue-monaco-editor'
|
||||
|
||||
import { panel } from '@/api/panel/dashboard'
|
||||
import dashboard from '@/api/panel/dashboard'
|
||||
import CronNaivePlugin from '@vue-js-cron/naive-ui'
|
||||
|
||||
async function setupApp() {
|
||||
const app = createApp(App)
|
||||
app.use(VueMonacoEditorPlugin, {
|
||||
paths: {
|
||||
vs: '/assets/vs'
|
||||
vs: window.location.origin + '/assets/vs'
|
||||
},
|
||||
'vs/nls': {
|
||||
availableLanguages: { '*': 'zh-cn' }
|
||||
@@ -38,7 +38,7 @@ async function setupApp() {
|
||||
|
||||
const setupPanel = async () => {
|
||||
const themeStore = useThemeStore()
|
||||
useRequest(panel, {
|
||||
useRequest(dashboard.panel, {
|
||||
initialData: {
|
||||
name: import.meta.env.VITE_APP_TITLE,
|
||||
locale: 'zh_CN'
|
||||
|
||||
@@ -5,9 +5,9 @@ export function createAppInstallGuard(router: Router) {
|
||||
router.beforeEach(async (to) => {
|
||||
const slug = to.path.split('/').pop()
|
||||
if (to.path.startsWith('/apps/') && slug) {
|
||||
await app.isInstalled(slug).then((res) => {
|
||||
if (!res.data.installed) {
|
||||
window.$message.error(`应用 ${res.data.name} 未安装`)
|
||||
useRequest(app.isInstalled(slug)).onSuccess(({ data }) => {
|
||||
if (!data.installed) {
|
||||
window.$message.error(`应用 ${data.name} 未安装`)
|
||||
return router.push({ name: 'app-index' })
|
||||
}
|
||||
})
|
||||
@@ -15,32 +15,26 @@ export function createAppInstallGuard(router: Router) {
|
||||
|
||||
// 网站
|
||||
if (to.path.startsWith('/website')) {
|
||||
await app.isInstalled('nginx').then((res) => {
|
||||
if (!res.data.installed) {
|
||||
window.$message.error(`Web 服务器 ${res.data.name} 未安装`)
|
||||
useRequest(app.isInstalled('nginx')).onSuccess(({ data }) => {
|
||||
if (!data.installed) {
|
||||
window.$message.error(`Web 服务器 ${data.name} 未安装`)
|
||||
return router.push({ name: 'app-index' })
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
// 容器
|
||||
if (to.path.startsWith('/container')) {
|
||||
let flag = false
|
||||
await app.isInstalled('docker').then((res) => {
|
||||
if (res.data.installed) {
|
||||
flag = true
|
||||
useRequest(app.isInstalled('docker')).onSuccess(({ data }) => {
|
||||
if (!data.installed) {
|
||||
useRequest(app.isInstalled('podman')).onSuccess(({ data }) => {
|
||||
if (!data.installed) {
|
||||
window.$message.error(`容器引擎 Docker / Podman 未安装`)
|
||||
return router.push({ name: 'app-index' })
|
||||
}
|
||||
})
|
||||
}
|
||||
})
|
||||
if (!flag) {
|
||||
await app.isInstalled('podman').then((res) => {
|
||||
if (res.data.installed) {
|
||||
flag = true
|
||||
}
|
||||
})
|
||||
}
|
||||
if (!flag) {
|
||||
window.$message.error(`容器引擎 Docker / Podman 未安装`)
|
||||
return router.push({ name: 'app-index' })
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
@@ -1,18 +1,4 @@
|
||||
import { useUserStore } from '@/store'
|
||||
import type { ErrorResolveResponse } from '~/types/axios'
|
||||
|
||||
/** 自定义错误 */
|
||||
export class AxiosRejectError extends Error {
|
||||
code?: number | string
|
||||
data?: any
|
||||
|
||||
constructor(rejectData: ErrorResolveResponse, options?: ErrorOptions) {
|
||||
const { code, message, data } = rejectData
|
||||
super(message, options)
|
||||
this.code = code
|
||||
this.data = data
|
||||
}
|
||||
}
|
||||
|
||||
export function resolveResError(code: number | string | undefined, message = ''): string {
|
||||
switch (code) {
|
||||
|
||||
+20
-30
@@ -1,53 +1,43 @@
|
||||
import { resolveResError } from '@/utils/http/helpers'
|
||||
import type { AlovaXHRResponse } from '@alova/adapter-xhr'
|
||||
import { xhrRequestAdapter } from '@alova/adapter-xhr'
|
||||
import { createAlova, Method } from 'alova'
|
||||
import adapterFetch from 'alova/fetch'
|
||||
import VueHook from 'alova/vue'
|
||||
import axios from 'axios'
|
||||
import { reqReject, reqResolve, resReject, resResolve } from './interceptors'
|
||||
|
||||
export function createAxios(options = {}) {
|
||||
const defaultOptions = {
|
||||
adapter: 'fetch',
|
||||
timeout: 0
|
||||
}
|
||||
const service = axios.create({
|
||||
...defaultOptions,
|
||||
...options
|
||||
})
|
||||
service.interceptors.request.use(reqResolve, reqReject)
|
||||
service.interceptors.response.use(resResolve, resReject)
|
||||
return service
|
||||
}
|
||||
|
||||
export const request = createAxios({
|
||||
baseURL: import.meta.env.VITE_BASE_API
|
||||
})
|
||||
|
||||
export const http = createAlova({
|
||||
id: 'panel',
|
||||
cacheFor: null,
|
||||
statesHook: VueHook,
|
||||
requestAdapter: adapterFetch(),
|
||||
requestAdapter: xhrRequestAdapter(),
|
||||
baseURL: import.meta.env.VITE_BASE_API,
|
||||
responded: {
|
||||
onSuccess: async (response: Response, method: Method) => {
|
||||
const ct = response.headers.get('Content-Type')
|
||||
const json =
|
||||
ct && ct.includes('application/json')
|
||||
? await response.json()
|
||||
: { code: response.status, message: await response.text() }
|
||||
onSuccess: async (response: AlovaXHRResponse, method: Method) => {
|
||||
const ct = response.headers['Content-Type'] || response.headers['content-type']
|
||||
let json
|
||||
try {
|
||||
if (ct && ct.includes('application/json')) {
|
||||
json = typeof response.data === 'string' ? JSON.parse(response.data) : response.data
|
||||
} else {
|
||||
json = { code: response.status, message: response.data }
|
||||
}
|
||||
} catch (error) {
|
||||
json = { code: response.status, message: 'JSON 解析失败' }
|
||||
}
|
||||
const { status, statusText } = response
|
||||
const { meta } = method
|
||||
if (status !== 200) {
|
||||
const code = json?.code ?? status
|
||||
const message = resolveResError(code, json?.message ?? statusText)
|
||||
const message = resolveResError(
|
||||
code,
|
||||
(typeof json?.message === 'string' && json.message.trim()) || statusText
|
||||
)
|
||||
const noAlert = meta?.noAlert
|
||||
if (!noAlert) {
|
||||
if (code === 422) {
|
||||
window.$message.error(message)
|
||||
} else if (code !== 401) {
|
||||
window.$dialog.error({
|
||||
title: '接口响应异常',
|
||||
title: '错误',
|
||||
content: message,
|
||||
maskClosable: false
|
||||
})
|
||||
|
||||
@@ -1,85 +0,0 @@
|
||||
import type { AxiosError, AxiosResponse } from 'axios'
|
||||
import type { RequestConfig } from '~/types/axios'
|
||||
import { AxiosRejectError, resolveResError } from './helpers'
|
||||
|
||||
/** 请求拦截 */
|
||||
export function reqResolve(config: RequestConfig) {
|
||||
return config
|
||||
}
|
||||
|
||||
/** 请求错误拦截 */
|
||||
export function reqReject(error: AxiosError) {
|
||||
return Promise.reject(error)
|
||||
}
|
||||
|
||||
/** 响应拦截 */
|
||||
export function resResolve(response: AxiosResponse) {
|
||||
const { data, status, config, statusText } = response
|
||||
if (status !== 200) {
|
||||
const code = data?.code ?? status
|
||||
const message = resolveResError(code, data?.message ?? statusText)
|
||||
const { noNeedTip } = config as RequestConfig
|
||||
|
||||
if (!noNeedTip) {
|
||||
if (code == 422) {
|
||||
window.$message.error(message)
|
||||
} else {
|
||||
if (code != 401) {
|
||||
window.$dialog.error({
|
||||
title: '请求返回异常',
|
||||
content: message,
|
||||
maskClosable: false
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return Promise.reject(new AxiosRejectError({ code, message, data: data || response }))
|
||||
}
|
||||
|
||||
return Promise.resolve(data)
|
||||
}
|
||||
|
||||
/** 响应错误拦截 */
|
||||
export function resReject(error: AxiosError) {
|
||||
if (!error || !error.response) {
|
||||
const code = error?.code
|
||||
/** 根据code处理对应的操作,并返回处理后的message */
|
||||
const message = resolveResError(code, error.message)
|
||||
window.$dialog.error({
|
||||
title: '请求出现异常',
|
||||
content: message,
|
||||
maskClosable: false
|
||||
})
|
||||
return Promise.reject(new AxiosRejectError({ code, message, data: error }))
|
||||
}
|
||||
const { data, status, config } = error.response
|
||||
let { code, message } = data as AxiosRejectError
|
||||
code = code ?? status
|
||||
message = message ?? error.message
|
||||
message = resolveResError(code, message)
|
||||
/** 需要错误提醒 */
|
||||
const { noNeedTip } = config as RequestConfig
|
||||
|
||||
if (!noNeedTip) {
|
||||
if (code == 422) {
|
||||
window.$message.error(message)
|
||||
} else {
|
||||
if (code != 401) {
|
||||
window.$dialog.error({
|
||||
title: '请求返回异常',
|
||||
content: message,
|
||||
maskClosable: false
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return Promise.reject(
|
||||
new AxiosRejectError({
|
||||
code,
|
||||
message,
|
||||
data: error.response?.data || error.response
|
||||
})
|
||||
)
|
||||
}
|
||||
@@ -8,17 +8,16 @@ import VersionModal from '@/views/app/VersionModal.vue'
|
||||
import { NButton, NDataTable, NFlex, NPopconfirm, NSwitch } from 'naive-ui'
|
||||
import { useI18n } from 'vue-i18n'
|
||||
|
||||
import app from '@/api/panel/app'
|
||||
import TheIcon from '@/components/custom/TheIcon.vue'
|
||||
import { router } from '@/router'
|
||||
import { renderIcon } from '@/utils'
|
||||
import type { App } from '@/views/app/types'
|
||||
import app from '../../api/panel/app'
|
||||
|
||||
const { t } = useI18n()
|
||||
|
||||
const versionModalShow = ref(false)
|
||||
const versionModalOperation = ref('安装')
|
||||
const versionModalInfo = ref<App>({} as App)
|
||||
const versionModalInfo = ref<any>({})
|
||||
|
||||
const columns: any = [
|
||||
{
|
||||
@@ -174,35 +173,31 @@ const columns: any = [
|
||||
}
|
||||
]
|
||||
|
||||
const apps = ref<App[]>([] as App[])
|
||||
|
||||
const selectedRowKeys = ref<any>([])
|
||||
|
||||
const pagination = reactive({
|
||||
page: 1,
|
||||
pageCount: 1,
|
||||
pageSize: 20,
|
||||
itemCount: 0,
|
||||
showQuickJumper: true,
|
||||
showSizePicker: true,
|
||||
pageSizes: [20, 50, 100, 200]
|
||||
})
|
||||
const { loading, data, page, total, pageSize, pageCount, refresh } = usePagination(
|
||||
(page, pageSize) => app.list(page, pageSize),
|
||||
{
|
||||
initialData: { total: 0, list: [] },
|
||||
initialPageSize: 20,
|
||||
total: (res: any) => res.total,
|
||||
data: (res: any) => res.items
|
||||
}
|
||||
)
|
||||
|
||||
const handleShowChange = (row: any) => {
|
||||
app.updateShow(row.slug, !row.show).then(() => {
|
||||
window.$message.success(t('appIndex.alerts.setup'))
|
||||
useRequest(app.updateShow(row.slug, !row.show)).onSuccess(() => {
|
||||
row.show = !row.show
|
||||
window.$message.success(t('appIndex.alerts.setup'))
|
||||
})
|
||||
}
|
||||
|
||||
const handleUpdate = (slug: string) => {
|
||||
app.update(slug).then(() => {
|
||||
useRequest(app.update(slug)).onSuccess(() => {
|
||||
window.$message.success(t('appIndex.alerts.update'))
|
||||
})
|
||||
}
|
||||
|
||||
const handleUninstall = (slug: string) => {
|
||||
app.uninstall(slug).then(() => {
|
||||
useRequest(app.uninstall(slug)).onSuccess(() => {
|
||||
window.$message.success(t('appIndex.alerts.uninstall'))
|
||||
})
|
||||
}
|
||||
@@ -212,37 +207,14 @@ const handleManage = (slug: string) => {
|
||||
}
|
||||
|
||||
const handleUpdateCache = () => {
|
||||
app.updateCache().then(() => {
|
||||
useRequest(app.updateCache()).onSuccess(() => {
|
||||
refresh()
|
||||
window.$message.success(t('appIndex.alerts.cache'))
|
||||
onPageChange(1)
|
||||
})
|
||||
}
|
||||
|
||||
const getAppList = async (page: number, limit: number) => {
|
||||
const { data } = await app.list(page, limit)
|
||||
return data
|
||||
}
|
||||
|
||||
const onChecked = (rowKeys: any) => {
|
||||
selectedRowKeys.value = rowKeys
|
||||
}
|
||||
|
||||
const onPageChange = (page: number) => {
|
||||
pagination.page = page
|
||||
getAppList(page, pagination.pageSize).then((res) => {
|
||||
apps.value = res.items
|
||||
pagination.itemCount = res.total
|
||||
pagination.pageCount = res.total / pagination.pageSize + 1
|
||||
})
|
||||
}
|
||||
|
||||
const onPageSizeChange = (pageSize: number) => {
|
||||
pagination.pageSize = pageSize
|
||||
onPageChange(1)
|
||||
}
|
||||
|
||||
onMounted(() => {
|
||||
onPageChange(pagination.page)
|
||||
refresh()
|
||||
})
|
||||
</script>
|
||||
|
||||
@@ -260,14 +232,21 @@ onMounted(() => {
|
||||
striped
|
||||
remote
|
||||
:scroll-x="1200"
|
||||
:loading="false"
|
||||
:loading="loading"
|
||||
:columns="columns"
|
||||
:data="apps"
|
||||
:data="data"
|
||||
:row-key="(row: any) => row.slug"
|
||||
:pagination="pagination"
|
||||
@update:checked-row-keys="onChecked"
|
||||
@update:page="onPageChange"
|
||||
@update:page-size="onPageSizeChange"
|
||||
v-model:page="page"
|
||||
v-model:pageSize="pageSize"
|
||||
:pagination="{
|
||||
page: page,
|
||||
pageCount: pageCount,
|
||||
pageSize: pageSize,
|
||||
itemCount: total,
|
||||
showQuickJumper: true,
|
||||
showSizePicker: true,
|
||||
pageSizes: [20, 50, 100, 200]
|
||||
}"
|
||||
/>
|
||||
<version-modal
|
||||
v-model:show="versionModalShow"
|
||||
|
||||
@@ -26,12 +26,11 @@ const options = computed(() => {
|
||||
})
|
||||
|
||||
const handleSubmit = () => {
|
||||
app
|
||||
.install(info.value.slug, model.value.channel)
|
||||
.then(() => {
|
||||
useRequest(app.install(info.value.slug, model.value.channel))
|
||||
.onSuccess(() => {
|
||||
window.$message.success(t('appIndex.alerts.install'))
|
||||
})
|
||||
.finally(() => {
|
||||
.onComplete(() => {
|
||||
doSubmit.value = false
|
||||
show.value = false
|
||||
model.value = {
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
<script setup lang="ts">
|
||||
import benchmark from '@/api/apps/benchmark'
|
||||
import TheIcon from '@/components/custom/TheIcon.vue'
|
||||
|
||||
defineOptions({
|
||||
name: 'apps-benchmark-index'
|
||||
})
|
||||
|
||||
import benchmark from '@/api/apps/benchmark'
|
||||
import TheIcon from '@/components/custom/TheIcon.vue'
|
||||
|
||||
const inTest = ref(false)
|
||||
const current = ref('CPU')
|
||||
const progress = ref(0)
|
||||
@@ -102,11 +102,11 @@ const handleTest = async () => {
|
||||
current.value = test
|
||||
if (test != 'memory' && test != 'disk') {
|
||||
for (let j = 0; j < 2; j++) {
|
||||
const { data } = await benchmark.test(test, j === 1)
|
||||
cpu.value[test as keyof typeof cpu.value][j === 1 ? 'multi' : 'single'] = data
|
||||
cpu.value[test as keyof typeof cpu.value][j === 1 ? 'multi' : 'single'] =
|
||||
await benchmark.test(test, j === 1)
|
||||
}
|
||||
} else {
|
||||
const { data } = await benchmark.test(test, false)
|
||||
const data = await benchmark.test(test, false)
|
||||
if (test === 'memory') {
|
||||
memory.value = data
|
||||
} else {
|
||||
|
||||
@@ -6,14 +6,14 @@ defineOptions({
|
||||
import Editor from '@guolao/vue-monaco-editor'
|
||||
import { NButton, NPopconfirm } from 'naive-ui'
|
||||
|
||||
import { getConfig, updateConfig } from '@/api/apps/docker'
|
||||
import docker from '@/api/apps/docker'
|
||||
import systemctl from '@/api/panel/systemctl'
|
||||
|
||||
const currentTab = ref('status')
|
||||
const status = ref(false)
|
||||
const isEnabled = ref(false)
|
||||
|
||||
const { data: config }: { data: any } = useRequest(getConfig, {
|
||||
const { data: config } = useRequest(docker.getConfig, {
|
||||
initialData: {
|
||||
config: ''
|
||||
}
|
||||
@@ -24,39 +24,38 @@ const statusStr = computed(() => {
|
||||
})
|
||||
|
||||
const getStatus = async () => {
|
||||
await systemctl.status('docker').then((res: any) => {
|
||||
status.value = res.data
|
||||
})
|
||||
status.value = await systemctl.status('docker')
|
||||
}
|
||||
|
||||
const getIsEnabled = async () => {
|
||||
await systemctl.isEnabled('docker').then((res: any) => {
|
||||
isEnabled.value = res.data
|
||||
})
|
||||
isEnabled.value = await systemctl.isEnabled('docker')
|
||||
}
|
||||
|
||||
const handleSaveConfig = async () => {
|
||||
useRequest(() => updateConfig(config.value)).onSuccess(() => {
|
||||
const handleSaveConfig = () => {
|
||||
useRequest(docker.updateConfig(config.value)).onSuccess(() => {
|
||||
window.$message.success('保存成功')
|
||||
})
|
||||
}
|
||||
|
||||
const handleStart = async () => {
|
||||
await systemctl.start('docker')
|
||||
window.$message.success('启动成功')
|
||||
await getStatus()
|
||||
const handleStart = () => {
|
||||
useRequest(systemctl.start('docker')).onSuccess(() => {
|
||||
window.$message.success('启动成功')
|
||||
getStatus()
|
||||
})
|
||||
}
|
||||
|
||||
const handleStop = async () => {
|
||||
await systemctl.stop('docker')
|
||||
window.$message.success('停止成功')
|
||||
await getStatus()
|
||||
const handleStop = () => {
|
||||
useRequest(systemctl.stop('docker')).onSuccess(() => {
|
||||
window.$message.success('停止成功')
|
||||
getStatus()
|
||||
})
|
||||
}
|
||||
|
||||
const handleRestart = async () => {
|
||||
await systemctl.restart('docker')
|
||||
window.$message.success('重启成功')
|
||||
await getStatus()
|
||||
const handleRestart = () => {
|
||||
useRequest(systemctl.restart('docker')).onSuccess(() => {
|
||||
window.$message.success('重启成功')
|
||||
getStatus()
|
||||
})
|
||||
}
|
||||
|
||||
const handleIsEnabled = async () => {
|
||||
@@ -92,7 +91,7 @@ onMounted(() => {
|
||||
<n-tabs v-model:value="currentTab" type="line" animated>
|
||||
<n-tab-pane name="status" tab="运行状态">
|
||||
<n-flex vertical>
|
||||
<n-card title="运行状态" rounded-10>
|
||||
<n-card title="运行状态">
|
||||
<template #header-extra>
|
||||
<n-switch v-model:value="isEnabled" @update:value="handleIsEnabled">
|
||||
<template #checked> 自启动开 </template>
|
||||
|
||||
@@ -10,7 +10,6 @@ import app from '@/api/panel/app'
|
||||
import systemctl from '@/api/panel/systemctl'
|
||||
import website from '@/api/panel/website'
|
||||
import { renderIcon } from '@/utils'
|
||||
import type { Jail } from '@/views/apps/fail2ban/types'
|
||||
|
||||
const currentTab = ref('status')
|
||||
const status = ref(false)
|
||||
@@ -65,13 +64,6 @@ const jailsColumns: any = [
|
||||
{ title: '最大尝试', key: 'max_retry', minWidth: 150, ellipsis: { tooltip: true } },
|
||||
{ title: '封禁时间', key: 'ban_time', minWidth: 150, ellipsis: { tooltip: true } },
|
||||
{ title: '周期', key: 'find_time', minWidth: 150, ellipsis: { tooltip: true } },
|
||||
{
|
||||
title: '日志路径',
|
||||
key: 'log_path',
|
||||
minWidth: 150,
|
||||
resizable: true,
|
||||
ellipsis: { tooltip: true }
|
||||
},
|
||||
{
|
||||
title: '操作',
|
||||
key: 'actions',
|
||||
@@ -126,8 +118,6 @@ const jailsColumns: any = [
|
||||
}
|
||||
]
|
||||
|
||||
const jails = ref<Jail[]>([])
|
||||
|
||||
const banedIPColumns: any = [
|
||||
{
|
||||
title: 'IP',
|
||||
@@ -173,31 +163,20 @@ const banedIPColumns: any = [
|
||||
}
|
||||
]
|
||||
|
||||
const pagination = reactive({
|
||||
page: 1,
|
||||
pageCount: 1,
|
||||
pageSize: 20,
|
||||
itemCount: 0,
|
||||
showQuickJumper: true,
|
||||
showSizePicker: true,
|
||||
pageSizes: [20, 50, 100, 200]
|
||||
})
|
||||
|
||||
const websites = ref<any[]>([])
|
||||
|
||||
const getWhiteList = async () => {
|
||||
await fail2ban.whitelist().then((res: any) => {
|
||||
white.value = res.data
|
||||
white.value = await fail2ban.whitelist()
|
||||
}
|
||||
|
||||
const handleSaveWhiteList = () => {
|
||||
useRequest(fail2ban.setWhitelist(white.value)).onSuccess(() => {
|
||||
window.$message.success('保存成功')
|
||||
})
|
||||
}
|
||||
|
||||
const handleSaveWhiteList = async () => {
|
||||
await fail2ban.setWhitelist(white.value)
|
||||
window.$message.success('保存成功')
|
||||
}
|
||||
|
||||
const getWebsiteList = async (page: number, limit: number) => {
|
||||
const { data } = await website.list(page, limit)
|
||||
const data = await website.list(page, limit)
|
||||
for (const item of data.items) {
|
||||
websites.value.push({
|
||||
label: item.name,
|
||||
@@ -207,35 +186,22 @@ const getWebsiteList = async (page: number, limit: number) => {
|
||||
addJailModel.value.website_name = websites.value[0]?.value
|
||||
}
|
||||
|
||||
const getJails = async (page: number, limit: number) => {
|
||||
const { data } = await fail2ban.jails(page, limit)
|
||||
return data
|
||||
}
|
||||
|
||||
const onPageChange = (page: number) => {
|
||||
pagination.page = page
|
||||
getJails(page, pagination.pageSize).then((res) => {
|
||||
jails.value = res.items
|
||||
pagination.itemCount = res.total
|
||||
pagination.pageCount = res.total / pagination.pageSize + 1
|
||||
})
|
||||
}
|
||||
|
||||
const onPageSizeChange = (pageSize: number) => {
|
||||
pagination.pageSize = pageSize
|
||||
onPageChange(1)
|
||||
}
|
||||
const { loading, data, page, total, pageSize, pageCount, refresh } = usePagination(
|
||||
(page, pageSize) => fail2ban.jails(page, pageSize),
|
||||
{
|
||||
initialData: { total: 0, list: [] },
|
||||
initialPageSize: 20,
|
||||
total: (res: any) => res.total,
|
||||
data: (res: any) => res.items
|
||||
}
|
||||
)
|
||||
|
||||
const getStatus = async () => {
|
||||
await systemctl.status('fail2ban').then((res: any) => {
|
||||
status.value = res.data
|
||||
})
|
||||
status.value = await systemctl.status('fail2ban')
|
||||
}
|
||||
|
||||
const getIsEnabled = async () => {
|
||||
await systemctl.isEnabled('fail2ban').then((res: any) => {
|
||||
isEnabled.value = res.data
|
||||
})
|
||||
isEnabled.value = await systemctl.isEnabled('fail2ban')
|
||||
}
|
||||
|
||||
const handleStart = async () => {
|
||||
@@ -273,39 +239,42 @@ const handleReload = async () => {
|
||||
await getStatus()
|
||||
}
|
||||
|
||||
const handleAddJail = async () => {
|
||||
await fail2ban.add(addJailModel.value)
|
||||
window.$message.success('添加成功')
|
||||
addJailModal.value = false
|
||||
onPageChange(1)
|
||||
const handleAddJail = () => {
|
||||
useRequest(fail2ban.add(addJailModel.value)).onSuccess(() => {
|
||||
refresh()
|
||||
window.$message.success('添加成功')
|
||||
addJailModal.value = false
|
||||
})
|
||||
}
|
||||
|
||||
const handleDeleteJail = async (name: string) => {
|
||||
await fail2ban.delete(name)
|
||||
window.$message.success('删除成功')
|
||||
onPageChange(1)
|
||||
const handleDeleteJail = (name: string) => {
|
||||
useRequest(fail2ban.delete(name)).onSuccess(() => {
|
||||
refresh()
|
||||
window.$message.success('删除成功')
|
||||
})
|
||||
}
|
||||
|
||||
const getJailInfo = async (name: string) => {
|
||||
const { data } = await fail2ban.jail(name)
|
||||
const data = await fail2ban.jail(name)
|
||||
jailCurrentlyBan.value = data.currently_ban
|
||||
jailTotalBan.value = data.total_ban
|
||||
jailBanedList.value = data.baned_list
|
||||
}
|
||||
|
||||
const handleUnBan = async (name: string, ip: string) => {
|
||||
await fail2ban.unban(name, ip)
|
||||
window.$message.success('解封成功')
|
||||
await getJailInfo(name)
|
||||
const handleUnBan = (name: string, ip: string) => {
|
||||
useRequest(fail2ban.unban(name, ip)).onSuccess(() => {
|
||||
window.$message.success('解封成功')
|
||||
getJailInfo(name)
|
||||
})
|
||||
}
|
||||
|
||||
onMounted(() => {
|
||||
refresh()
|
||||
getStatus()
|
||||
getIsEnabled()
|
||||
getWhiteList()
|
||||
onPageChange(1)
|
||||
app.isInstalled('nginx').then((res) => {
|
||||
if (res.data.installed) {
|
||||
useRequest(app.isInstalled('nginx')).onSuccess(({ data }) => {
|
||||
if (data.installed) {
|
||||
getWebsiteList(1, 10000)
|
||||
}
|
||||
})
|
||||
@@ -337,7 +306,7 @@ onMounted(() => {
|
||||
<n-tabs v-model:value="currentTab" type="line" animated>
|
||||
<n-tab-pane name="status" tab="运行状态">
|
||||
<n-space vertical>
|
||||
<n-card title="运行状态" rounded-10>
|
||||
<n-card title="运行状态">
|
||||
<template #header-extra>
|
||||
<n-switch v-model:value="isEnabled" @update:value="handleIsEnabled">
|
||||
<template #checked> 自启动开 </template>
|
||||
@@ -373,7 +342,7 @@ onMounted(() => {
|
||||
</n-space>
|
||||
</n-space>
|
||||
</n-card>
|
||||
<n-card title="IP 白名单" rounded-10>
|
||||
<n-card title="IP 白名单">
|
||||
<n-input
|
||||
v-model:value="white"
|
||||
type="textarea"
|
||||
@@ -384,17 +353,26 @@ onMounted(() => {
|
||||
</n-space>
|
||||
</n-tab-pane>
|
||||
<n-tab-pane name="jails" tab="规则管理">
|
||||
<n-card title="规则列表" :segmented="true" rounded-10>
|
||||
<n-card title="规则列表" :segmented="true">
|
||||
<n-data-table
|
||||
striped
|
||||
remote
|
||||
:scroll-x="1000"
|
||||
:loading="false"
|
||||
:loading="loading"
|
||||
:columns="jailsColumns"
|
||||
:data="jails"
|
||||
:data="data"
|
||||
:row-key="(row: any) => row.name"
|
||||
@update:page="onPageChange"
|
||||
@update:page-size="onPageSizeChange"
|
||||
v-model:page="page"
|
||||
v-model:pageSize="pageSize"
|
||||
:pagination="{
|
||||
page: page,
|
||||
pageCount: pageCount,
|
||||
pageSize: pageSize,
|
||||
itemCount: total,
|
||||
showQuickJumper: true,
|
||||
showSizePicker: true,
|
||||
pageSizes: [20, 50, 100, 200]
|
||||
}"
|
||||
/>
|
||||
</n-card>
|
||||
</n-tab-pane>
|
||||
@@ -472,7 +450,7 @@ onMounted(() => {
|
||||
<n-modal v-model:show="jailModal" title="查看规则">
|
||||
<n-card closable @close="() => (jailModal = false)" title="查看规则" style="width: 60vw">
|
||||
<n-space vertical>
|
||||
<n-card title="规则信息" :segmented="true" rounded-10>
|
||||
<n-card title="规则信息" :segmented="true">
|
||||
<n-space vertical>
|
||||
<n-space>
|
||||
<n-text>当前封禁</n-text>
|
||||
@@ -484,7 +462,7 @@ onMounted(() => {
|
||||
</n-space>
|
||||
</n-space>
|
||||
</n-card>
|
||||
<n-card title="封禁列表" :segmented="true" rounded-10>
|
||||
<n-card title="封禁列表" :segmented="true">
|
||||
<n-data-table
|
||||
striped
|
||||
remote
|
||||
|
||||
@@ -1,8 +0,0 @@
|
||||
export interface Jail {
|
||||
name: string
|
||||
enabled: boolean
|
||||
log_path: string
|
||||
max_retry: number
|
||||
find_time: number
|
||||
ban_time: number
|
||||
}
|
||||
@@ -31,35 +31,26 @@ const statusStr = computed(() => {
|
||||
})
|
||||
|
||||
const getStatus = async () => {
|
||||
await systemctl.status('frps').then((res: any) => {
|
||||
status.value.frps = res.data
|
||||
})
|
||||
await systemctl.status('frpc').then((res: any) => {
|
||||
status.value.frpc = res.data
|
||||
})
|
||||
status.value.frps = await systemctl.status('frps')
|
||||
status.value.frpc = await systemctl.status('frpc')
|
||||
}
|
||||
|
||||
const getIsEnabled = async () => {
|
||||
await systemctl.isEnabled('frps').then((res: any) => {
|
||||
isEnabled.value.frps = res.data
|
||||
})
|
||||
await systemctl.isEnabled('frpc').then((res: any) => {
|
||||
isEnabled.value.frpc = res.data
|
||||
})
|
||||
isEnabled.value.frps = await systemctl.isEnabled('frps')
|
||||
isEnabled.value.frpc = await systemctl.isEnabled('frpc')
|
||||
}
|
||||
|
||||
const getConfig = async () => {
|
||||
frp.config('frps').then((res: any) => {
|
||||
config.value.frps = res.data
|
||||
})
|
||||
frp.config('frpc').then((res: any) => {
|
||||
config.value.frpc = res.data
|
||||
})
|
||||
config.value.frps = await frp.config('frps')
|
||||
config.value.frpc = await frp.config('frpc')
|
||||
}
|
||||
|
||||
const handleSaveConfig = async (service: string) => {
|
||||
await frp.saveConfig(service, config.value[service as keyof typeof config.value])
|
||||
window.$message.success('保存成功')
|
||||
const handleSaveConfig = (service: string) => {
|
||||
useRequest(frp.saveConfig(service, config.value[service as keyof typeof config.value])).onSuccess(
|
||||
() => {
|
||||
window.$message.success('保存成功')
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
const handleStart = async (name: string) => {
|
||||
@@ -103,7 +94,7 @@ onMounted(() => {
|
||||
<n-tabs v-model:value="currentTab" type="line" animated>
|
||||
<n-tab-pane name="frps" tab="Frps">
|
||||
<n-space vertical>
|
||||
<n-card title="运行状态" rounded-10>
|
||||
<n-card title="运行状态">
|
||||
<template #header-extra>
|
||||
<n-switch v-model:value="isEnabled.frps" @update:value="handleIsEnabled('frps')">
|
||||
<template #checked> 自启动开 </template>
|
||||
@@ -135,7 +126,7 @@ onMounted(() => {
|
||||
</n-space>
|
||||
</n-space>
|
||||
</n-card>
|
||||
<n-card title="修改配置" rounded-10>
|
||||
<n-card title="修改配置">
|
||||
<template #header-extra>
|
||||
<n-button type="primary" @click="handleSaveConfig('frps')">
|
||||
<TheIcon :size="18" icon="material-symbols:save-outline-rounded" />
|
||||
@@ -159,7 +150,7 @@ onMounted(() => {
|
||||
</n-tab-pane>
|
||||
<n-tab-pane name="frpc" tab="Frpc">
|
||||
<n-space vertical>
|
||||
<n-card title="运行状态" rounded-10>
|
||||
<n-card title="运行状态">
|
||||
<template #header-extra>
|
||||
<n-switch v-model:value="isEnabled.frpc" @update:value="handleIsEnabled('frpc')">
|
||||
<template #checked> 自启动开 </template>
|
||||
@@ -191,7 +182,7 @@ onMounted(() => {
|
||||
</n-space>
|
||||
</n-space>
|
||||
</n-card>
|
||||
<n-card title="修改配置" rounded-10>
|
||||
<n-card title="修改配置">
|
||||
<template #header-extra>
|
||||
<n-button type="primary" @click="handleSaveConfig('frpc')">
|
||||
<TheIcon :size="18" icon="material-symbols:save-outline-rounded" />
|
||||
|
||||
@@ -19,26 +19,21 @@ const statusStr = computed(() => {
|
||||
})
|
||||
|
||||
const getStatus = async () => {
|
||||
await systemctl.status('gitea').then((res: any) => {
|
||||
status.value = res.data
|
||||
})
|
||||
status.value = await systemctl.status('gitea')
|
||||
}
|
||||
|
||||
const getIsEnabled = async () => {
|
||||
await systemctl.isEnabled('gitea').then((res: any) => {
|
||||
isEnabled.value = res.data
|
||||
})
|
||||
isEnabled.value = await systemctl.isEnabled('gitea')
|
||||
}
|
||||
|
||||
const getConfig = async () => {
|
||||
gitea.config().then((res: any) => {
|
||||
config.value = res.data
|
||||
})
|
||||
config.value = await gitea.config()
|
||||
}
|
||||
|
||||
const handleSaveConfig = async () => {
|
||||
await gitea.saveConfig(config.value)
|
||||
window.$message.success('保存成功')
|
||||
const handleSaveConfig = () => {
|
||||
useRequest(gitea.saveConfig(config.value)).onSuccess(() => {
|
||||
window.$message.success('保存成功')
|
||||
})
|
||||
}
|
||||
|
||||
const handleStart = async () => {
|
||||
@@ -92,7 +87,7 @@ onMounted(() => {
|
||||
</template>
|
||||
<n-tabs v-model:value="currentTab" type="line" animated>
|
||||
<n-tab-pane name="status" tab="运行状态">
|
||||
<n-card title="运行状态" rounded-10>
|
||||
<n-card title="运行状态">
|
||||
<template #header-extra>
|
||||
<n-switch v-model:value="isEnabled" @update:value="handleIsEnabled">
|
||||
<template #checked> 自启动开 </template>
|
||||
|
||||
@@ -6,7 +6,7 @@ defineOptions({
|
||||
import Editor from '@guolao/vue-monaco-editor'
|
||||
import { NButton, NDataTable, NPopconfirm } from 'naive-ui'
|
||||
|
||||
import { getConfig, getLoad, updateConfig } from '@/api/apps/memcached'
|
||||
import memcached from '@/api/apps/memcached'
|
||||
import systemctl from '@/api/panel/systemctl'
|
||||
|
||||
const currentTab = ref('status')
|
||||
@@ -36,30 +36,26 @@ const loadColumns: any = [
|
||||
}
|
||||
]
|
||||
|
||||
const { data: load }: { data: any } = useRequest(getLoad, {
|
||||
const { data: load } = useRequest(memcached.getLoad, {
|
||||
initialData: []
|
||||
})
|
||||
|
||||
const getStatus = async () => {
|
||||
await systemctl.status('memcached').then((res: any) => {
|
||||
status.value = res.data
|
||||
})
|
||||
status.value = await systemctl.status('memcached')
|
||||
}
|
||||
|
||||
const getIsEnabled = async () => {
|
||||
await systemctl.isEnabled('memcached').then((res: any) => {
|
||||
isEnabled.value = res.data
|
||||
})
|
||||
isEnabled.value = await systemctl.isEnabled('memcached')
|
||||
}
|
||||
|
||||
const { data: config }: { data: any } = useRequest(getConfig, {
|
||||
const { data: config } = useRequest(memcached.getConfig, {
|
||||
initialData: {
|
||||
config: ''
|
||||
}
|
||||
})
|
||||
|
||||
const handleSaveConfig = async () => {
|
||||
useRequest(() => updateConfig(config.value)).onSuccess(() => {
|
||||
const handleSaveConfig = () => {
|
||||
useRequest(memcached.updateConfig(config.value)).onSuccess(() => {
|
||||
window.$message.success('保存成功')
|
||||
})
|
||||
}
|
||||
@@ -115,7 +111,7 @@ onMounted(() => {
|
||||
<n-tabs v-model:value="currentTab" type="line" animated>
|
||||
<n-tab-pane name="status" tab="运行状态">
|
||||
<n-space vertical>
|
||||
<n-card title="运行状态" rounded-10>
|
||||
<n-card title="运行状态">
|
||||
<template #header-extra>
|
||||
<n-switch v-model:value="isEnabled" @update:value="handleIsEnabled">
|
||||
<template #checked> 自启动开 </template>
|
||||
|
||||
@@ -12,9 +12,19 @@ import systemctl from '@/api/panel/systemctl'
|
||||
const currentTab = ref('status')
|
||||
const status = ref(false)
|
||||
const isEnabled = ref(false)
|
||||
const config = ref('')
|
||||
const slowLog = ref('')
|
||||
const rootPassword = ref('')
|
||||
|
||||
const { data: rootPassword } = useRequest(mysql.rootPassword, {
|
||||
initialData: ''
|
||||
})
|
||||
const { data: config } = useRequest(mysql.config, {
|
||||
initialData: ''
|
||||
})
|
||||
const { data: slowLog } = useRequest(mysql.slowLog, {
|
||||
initialData: ''
|
||||
})
|
||||
const { data: load } = useRequest(mysql.load, {
|
||||
initialData: []
|
||||
})
|
||||
|
||||
const statusType = computed(() => {
|
||||
return status.value ? 'success' : 'error'
|
||||
@@ -39,56 +49,32 @@ const loadColumns: any = [
|
||||
}
|
||||
]
|
||||
|
||||
const load = ref<any[]>([])
|
||||
|
||||
const getLoad = async () => {
|
||||
const { data } = await mysql.load()
|
||||
return data
|
||||
const getStatus = async () => {
|
||||
status.value = await systemctl.status('mysqld')
|
||||
}
|
||||
|
||||
const getIsEnabled = async () => {
|
||||
await systemctl.isEnabled('mysqld').then((res: any) => {
|
||||
isEnabled.value = res.data
|
||||
isEnabled.value = await systemctl.isEnabled('mysqld')
|
||||
}
|
||||
|
||||
const handleSaveConfig = () => {
|
||||
useRequest(mysql.saveConfig(config.value)).onSuccess(() => {
|
||||
window.$message.success('保存成功')
|
||||
})
|
||||
}
|
||||
|
||||
const getStatus = async () => {
|
||||
await systemctl.status('mysqld').then((res: any) => {
|
||||
status.value = res.data
|
||||
const handleClearErrorLog = () => {
|
||||
useRequest(mysql.clearErrorLog()).onSuccess(() => {
|
||||
window.$message.success('清空成功')
|
||||
})
|
||||
}
|
||||
|
||||
const getRootPassword = async () => {
|
||||
await mysql.rootPassword().then((res: any) => {
|
||||
rootPassword.value = res.data
|
||||
const handleClearSlowLog = () => {
|
||||
useRequest(mysql.clearSlowLog()).onSuccess(() => {
|
||||
window.$message.success('清空成功')
|
||||
})
|
||||
}
|
||||
|
||||
const getSlowLog = async () => {
|
||||
const { data } = await mysql.slowLog()
|
||||
return data
|
||||
}
|
||||
|
||||
const getConfig = async () => {
|
||||
const { data } = await mysql.config()
|
||||
return data
|
||||
}
|
||||
|
||||
const handleSaveConfig = async () => {
|
||||
await mysql.saveConfig(config.value)
|
||||
window.$message.success('保存成功')
|
||||
}
|
||||
|
||||
const handleClearErrorLog = async () => {
|
||||
await mysql.clearErrorLog()
|
||||
window.$message.success('清空成功')
|
||||
}
|
||||
|
||||
const handleClearSlowLog = async () => {
|
||||
await mysql.clearSlowLog()
|
||||
window.$message.success('清空成功')
|
||||
}
|
||||
|
||||
const handleIsEnabled = async () => {
|
||||
if (isEnabled.value) {
|
||||
await systemctl.enable('mysqld')
|
||||
@@ -118,12 +104,6 @@ const handleRestart = async () => {
|
||||
await getStatus()
|
||||
}
|
||||
|
||||
const handleReload = async () => {
|
||||
await systemctl.reload('mysqld')
|
||||
window.$message.success('重载成功')
|
||||
await getStatus()
|
||||
}
|
||||
|
||||
const handleSetRootPassword = async () => {
|
||||
await mysql.setRootPassword(rootPassword.value)
|
||||
window.$message.success('修改成功')
|
||||
@@ -132,16 +112,6 @@ const handleSetRootPassword = async () => {
|
||||
onMounted(() => {
|
||||
getStatus()
|
||||
getIsEnabled()
|
||||
getRootPassword()
|
||||
getLoad().then((res) => {
|
||||
load.value = res
|
||||
})
|
||||
getSlowLog().then((res) => {
|
||||
slowLog.value = res
|
||||
})
|
||||
getConfig().then((res) => {
|
||||
config.value = res
|
||||
})
|
||||
})
|
||||
</script>
|
||||
|
||||
@@ -179,7 +149,7 @@ onMounted(() => {
|
||||
<n-tabs v-model:value="currentTab" type="line" animated>
|
||||
<n-tab-pane name="status" tab="运行状态">
|
||||
<n-space vertical>
|
||||
<n-card title="运行状态" rounded-10>
|
||||
<n-card title="运行状态">
|
||||
<template #header-extra>
|
||||
<n-switch v-model:value="isEnabled" @update:value="handleIsEnabled">
|
||||
<template #checked> 自启动开 </template>
|
||||
@@ -208,14 +178,10 @@ onMounted(() => {
|
||||
<TheIcon :size="18" icon="material-symbols:replay-rounded" />
|
||||
重启
|
||||
</n-button>
|
||||
<n-button type="primary" @click="handleReload">
|
||||
<TheIcon :size="20" icon="material-symbols:refresh-rounded" />
|
||||
重载
|
||||
</n-button>
|
||||
</n-space>
|
||||
</n-space>
|
||||
</n-card>
|
||||
<n-card title="Root 密码" rounded-10>
|
||||
<n-card title="Root 密码">
|
||||
<n-space vertical>
|
||||
<n-input
|
||||
v-model:value="rootPassword"
|
||||
|
||||
@@ -12,8 +12,16 @@ import systemctl from '@/api/panel/systemctl'
|
||||
const currentTab = ref('status')
|
||||
const status = ref(false)
|
||||
const isEnabled = ref(false)
|
||||
const config = ref('')
|
||||
const errorLog = ref('')
|
||||
|
||||
const { data: config } = useRequest(nginx.config, {
|
||||
initialData: ''
|
||||
})
|
||||
const { data: errorLog } = useRequest(nginx.errorLog, {
|
||||
initialData: ''
|
||||
})
|
||||
const { data: load } = useRequest(nginx.load, {
|
||||
initialData: []
|
||||
})
|
||||
|
||||
const statusType = computed(() => {
|
||||
return status.value ? 'success' : 'error'
|
||||
@@ -39,43 +47,24 @@ const columns: any = [
|
||||
}
|
||||
]
|
||||
|
||||
const load = ref<any[]>([])
|
||||
|
||||
const getLoad = async () => {
|
||||
const { data } = await nginx.load()
|
||||
return data
|
||||
}
|
||||
|
||||
const getStatus = async () => {
|
||||
await systemctl.status('nginx').then((res: any) => {
|
||||
status.value = res.data
|
||||
})
|
||||
status.value = await systemctl.status('nginx')
|
||||
}
|
||||
|
||||
const getIsEnabled = async () => {
|
||||
await systemctl.isEnabled('nginx').then((res: any) => {
|
||||
isEnabled.value = res.data
|
||||
isEnabled.value = await systemctl.isEnabled('nginx')
|
||||
}
|
||||
|
||||
const handleSaveConfig = () => {
|
||||
useRequest(nginx.saveConfig(config.value)).onSuccess(() => {
|
||||
window.$message.success('保存成功')
|
||||
})
|
||||
}
|
||||
|
||||
const getErrorLog = async () => {
|
||||
const { data } = await nginx.errorLog()
|
||||
return data
|
||||
}
|
||||
|
||||
const getConfig = async () => {
|
||||
const { data } = await nginx.config()
|
||||
return data
|
||||
}
|
||||
|
||||
const handleSaveConfig = async () => {
|
||||
await nginx.saveConfig(config.value)
|
||||
window.$message.success('保存成功')
|
||||
}
|
||||
|
||||
const handleClearErrorLog = async () => {
|
||||
await nginx.clearErrorLog()
|
||||
window.$message.success('清空成功')
|
||||
const handleClearErrorLog = () => {
|
||||
useRequest(nginx.clearErrorLog()).onSuccess(() => {
|
||||
window.$message.success('清空成功')
|
||||
})
|
||||
}
|
||||
|
||||
const handleIsEnabled = async () => {
|
||||
@@ -116,15 +105,6 @@ const handleReload = async () => {
|
||||
onMounted(() => {
|
||||
getStatus()
|
||||
getIsEnabled()
|
||||
getLoad().then((res) => {
|
||||
load.value = res
|
||||
})
|
||||
getErrorLog().then((res) => {
|
||||
errorLog.value = res
|
||||
})
|
||||
getConfig().then((res) => {
|
||||
config.value = res
|
||||
})
|
||||
})
|
||||
</script>
|
||||
|
||||
@@ -152,7 +132,7 @@ onMounted(() => {
|
||||
</template>
|
||||
<n-tabs v-model:value="currentTab" type="line" animated>
|
||||
<n-tab-pane name="status" tab="运行状态">
|
||||
<n-card title="运行状态" rounded-10>
|
||||
<n-card title="运行状态">
|
||||
<template #header-extra>
|
||||
<n-switch v-model:value="isEnabled" @update:value="handleIsEnabled">
|
||||
<template #checked> 自启动开 </template>
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user