diff --git a/internal/apps/apps.go b/internal/apps/apps.go
index 246d4a34..44730845 100644
--- a/internal/apps/apps.go
+++ b/internal/apps/apps.go
@@ -4,6 +4,7 @@ import (
"github.com/google/wire"
"github.com/tnb-labs/panel/internal/apps/benchmark"
+ "github.com/tnb-labs/panel/internal/apps/codeserver"
"github.com/tnb-labs/panel/internal/apps/docker"
"github.com/tnb-labs/panel/internal/apps/fail2ban"
"github.com/tnb-labs/panel/internal/apps/frp"
@@ -31,6 +32,7 @@ import (
var ProviderSet = wire.NewSet(
benchmark.NewApp,
+ codeserver.NewApp,
docker.NewApp,
fail2ban.NewApp,
frp.NewApp,
diff --git a/internal/apps/codeserver/app.go b/internal/apps/codeserver/app.go
new file mode 100644
index 00000000..8167a7a3
--- /dev/null
+++ b/internal/apps/codeserver/app.go
@@ -0,0 +1,47 @@
+package codeserver
+
+import (
+ "net/http"
+
+ "github.com/go-chi/chi/v5"
+
+ "github.com/tnb-labs/panel/internal/service"
+ "github.com/tnb-labs/panel/pkg/io"
+ "github.com/tnb-labs/panel/pkg/systemctl"
+)
+
+type App struct{}
+
+func NewApp() *App {
+ return &App{}
+}
+
+func (s *App) Route(r chi.Router) {
+ r.Get("/config", s.GetConfig)
+ r.Post("/config", s.UpdateConfig)
+}
+
+func (s *App) GetConfig(w http.ResponseWriter, r *http.Request) {
+ config, _ := io.Read("/root/.config/code-server/config.yaml")
+ service.Success(w, config)
+}
+
+func (s *App) UpdateConfig(w http.ResponseWriter, r *http.Request) {
+ req, err := service.Bind[UpdateConfig](r)
+ if err != nil {
+ service.Error(w, http.StatusUnprocessableEntity, "%v", err)
+ return
+ }
+
+ if err = io.Write("/root/.config/code-server/config.yaml", req.Config, 0600); err != nil {
+ service.Error(w, http.StatusInternalServerError, "%v", err)
+ return
+ }
+
+ if err = systemctl.Restart("code-server"); err != nil {
+ service.Error(w, http.StatusInternalServerError, "%v", err)
+ return
+ }
+
+ service.Success(w, nil)
+}
diff --git a/internal/apps/codeserver/request.go b/internal/apps/codeserver/request.go
new file mode 100644
index 00000000..122e8eb5
--- /dev/null
+++ b/internal/apps/codeserver/request.go
@@ -0,0 +1,5 @@
+package codeserver
+
+type UpdateConfig struct {
+ Config string `form:"config" json:"config" validate:"required"`
+}
diff --git a/internal/bootstrap/apps.go b/internal/bootstrap/apps.go
index e5ace2a1..88606d6d 100644
--- a/internal/bootstrap/apps.go
+++ b/internal/bootstrap/apps.go
@@ -2,6 +2,7 @@ package bootstrap
import (
"github.com/tnb-labs/panel/internal/apps/benchmark"
+ "github.com/tnb-labs/panel/internal/apps/codeserver"
"github.com/tnb-labs/panel/internal/apps/docker"
"github.com/tnb-labs/panel/internal/apps/fail2ban"
"github.com/tnb-labs/panel/internal/apps/frp"
@@ -30,6 +31,7 @@ import (
func NewLoader(
benchmark *benchmark.App,
+ codeserver *codeserver.App,
docker *docker.App,
fail2ban *fail2ban.App,
frp *frp.App,
@@ -55,6 +57,6 @@ func NewLoader(
toolbox *toolbox.App,
) *apploader.Loader {
loader := new(apploader.Loader)
- loader.Add(benchmark, docker, fail2ban, frp, gitea, memcached, minio, mysql, nginx, php74, php80, php81, php82, php83, php84, phpmyadmin, podman, postgresql, pureftpd, redis, rsync, s3fs, supervisor, toolbox)
+ loader.Add(benchmark, codeserver, docker, fail2ban, frp, gitea, memcached, minio, mysql, nginx, php74, php80, php81, php82, php83, php84, phpmyadmin, podman, postgresql, pureftpd, redis, rsync, s3fs, supervisor, toolbox)
return loader
}
diff --git a/web/src/api/apps/codeserver/index.ts b/web/src/api/apps/codeserver/index.ts
new file mode 100644
index 00000000..987d5e58
--- /dev/null
+++ b/web/src/api/apps/codeserver/index.ts
@@ -0,0 +1,8 @@
+import { http } from '@/utils'
+
+export default {
+ // 获取配置
+ config: (): any => http.Get('/apps/codeserver/config'),
+ // 保存配置
+ saveConfig: (config: string): any => http.Post('/apps/codeserver/config', { config })
+}
diff --git a/web/src/views/apps/codeserver/IndexView.vue b/web/src/views/apps/codeserver/IndexView.vue
new file mode 100644
index 00000000..67d8bcd8
--- /dev/null
+++ b/web/src/views/apps/codeserver/IndexView.vue
@@ -0,0 +1,153 @@
+
+
+
+
+
+
+
+ {{ $gettext('Save') }}
+
+
+
+
+
+
+
+ {{ $gettext('Autostart On') }}
+ {{ $gettext('Autostart Off') }}
+
+
+
+
+ {{ statusStr }}
+
+
+
+
+ {{ $gettext('Start') }}
+
+
+
+
+
+ {{ $gettext('Stop') }}
+
+
+ {{ $gettext('Are you sure you want to stop Code Server?') }}
+
+
+
+ {{ $gettext('Restart') }}
+
+
+
+
+
+
+
+
+ {{
+ $gettext(
+ 'This modifies the Code Server configuration file. If you do not understand the meaning of each parameter, please do not modify it randomly!'
+ )
+ }}
+
+
+
+
+
+
+
+
+
+
diff --git a/web/src/views/apps/codeserver/route.ts b/web/src/views/apps/codeserver/route.ts
new file mode 100644
index 00000000..9366c5ca
--- /dev/null
+++ b/web/src/views/apps/codeserver/route.ts
@@ -0,0 +1,23 @@
+import type { RouteType } from '~/types/router'
+
+const Layout = () => import('@/layout/IndexView.vue')
+
+export default {
+ name: 'codeserver',
+ path: '/apps/codeserver',
+ component: Layout,
+ isHidden: true,
+ children: [
+ {
+ name: 'apps-codeserver-index',
+ path: '',
+ component: () => import('./IndexView.vue'),
+ meta: {
+ title: 'Code Server',
+ icon: 'simple-icons:coder',
+ role: ['admin'],
+ requireAuth: true
+ }
+ }
+ ]
+} as RouteType