mirror of
https://github.com/acepanel/panel.git
synced 2026-02-04 06:47:20 +08:00
feat: 一堆调整
This commit is contained in:
@@ -82,7 +82,7 @@ func initWeb() (*app.Web, error) {
|
||||
settingRepo := data.NewSettingRepo(locale, db, koanf, taskRepo)
|
||||
cronRepo := data.NewCronRepo(locale, db)
|
||||
backupRepo := data.NewBackupRepo(locale, db, settingRepo, websiteRepo)
|
||||
dashboardService := service.NewDashboardService(locale, koanf, taskRepo, websiteRepo, appRepo, settingRepo, cronRepo, backupRepo)
|
||||
homeService := service.NewHomeService(locale, koanf, taskRepo, websiteRepo, appRepo, settingRepo, cronRepo, backupRepo)
|
||||
taskService := service.NewTaskService(taskRepo)
|
||||
websiteService := service.NewWebsiteService(websiteRepo, settingRepo)
|
||||
databaseService := service.NewDatabaseService(databaseRepo)
|
||||
@@ -142,7 +142,7 @@ func initWeb() (*app.Web, error) {
|
||||
s3fsApp := s3fs.NewApp(locale)
|
||||
supervisorApp := supervisor.NewApp(locale)
|
||||
loader := bootstrap.NewLoader(codeserverApp, dockerApp, fail2banApp, frpApp, giteaApp, memcachedApp, minioApp, mysqlApp, nginxApp, php74App, php80App, php81App, php82App, php83App, php84App, phpmyadminApp, podmanApp, postgresqlApp, pureftpdApp, redisApp, rsyncApp, s3fsApp, supervisorApp)
|
||||
http := route.NewHttp(koanf, userService, userTokenService, dashboardService, taskService, websiteService, databaseService, databaseServerService, databaseUserService, backupService, certService, certDNSService, certAccountService, appService, cronService, processService, safeService, firewallService, sshService, containerService, containerComposeService, containerNetworkService, containerImageService, containerVolumeService, fileService, monitorService, settingService, systemctlService, toolboxSystemService, toolboxBenchmarkService, loader)
|
||||
http := route.NewHttp(koanf, userService, userTokenService, homeService, taskService, websiteService, databaseService, databaseServerService, databaseUserService, backupService, certService, certDNSService, certAccountService, appService, cronService, processService, safeService, firewallService, sshService, containerService, containerComposeService, containerNetworkService, containerImageService, containerVolumeService, fileService, monitorService, settingService, systemctlService, toolboxSystemService, toolboxBenchmarkService, loader)
|
||||
wsService := service.NewWsService(locale, koanf, logger, sshRepo)
|
||||
ws := route.NewWs(wsService)
|
||||
mux, err := bootstrap.NewRouter(locale, middlewares, http, ws)
|
||||
|
||||
6
go.sum
6
go.sum
@@ -167,6 +167,8 @@ github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXi
|
||||
github.com/google/pprof v0.0.0-20181206194817-3ea8567a2e57/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc=
|
||||
github.com/google/pprof v0.0.0-20190515194954-54271f7e092f/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc=
|
||||
github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI=
|
||||
github.com/google/subcommands v1.2.0 h1:vWQspBTo2nEqTUFita5/KeEWlUL8kQObDFbub/EN9oE=
|
||||
github.com/google/subcommands v1.2.0/go.mod h1:ZjhPrFU+Olkh9WazFPsl27BQ4UPiG37m3yTrtFlrHVk=
|
||||
github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=
|
||||
github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
||||
github.com/google/wire v0.7.0 h1:JxUKI6+CVBgCO2WToKy/nQk0sS+amI9z9EjVmdaocj4=
|
||||
@@ -462,6 +464,8 @@ golang.org/x/mobile v0.0.0-20190312151609-d3739f865fa6/go.mod h1:z+o9i4GpDbdi3rU
|
||||
golang.org/x/mobile v0.0.0-20190719004257-d2bd2a29d028/go.mod h1:E/iHnbuqvinMTCcRqshq8CkpyQDoeVncDDYHnLhea+o=
|
||||
golang.org/x/mod v0.0.0-20190513183733-4bf6d317e70e/go.mod h1:mXi4GBBbnImb6dmsKGUJ2LatrhH/nqhxcFungHvyanc=
|
||||
golang.org/x/mod v0.1.0/go.mod h1:0QHyrYULN0/3qlju5TqG8bIK38QM8yzMo5ekMj3DlcY=
|
||||
golang.org/x/mod v0.29.0 h1:HV8lRxZC4l2cr3Zq1LvtOsi/ThTgWnUk/y64QSs8GwA=
|
||||
golang.org/x/mod v0.29.0/go.mod h1:NyhrlYXJ2H4eJiRy/WDBO6HMqZQ6q9nk4JzS3NuCK+w=
|
||||
golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20181023162649-9b4f9f5ad519/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
@@ -534,6 +538,8 @@ golang.org/x/tools v0.0.0-20190816200558-6889da9d5479/go.mod h1:b+2E5dAYhXwXZwtn
|
||||
golang.org/x/tools v0.0.0-20190911174233-4f2ddba30aff/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||
golang.org/x/tools v0.0.0-20191012152004-8de300cfc20a/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||
golang.org/x/tools v0.0.0-20191112195655-aa38f8e97acc/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||
golang.org/x/tools v0.38.0 h1:Hx2Xv8hISq8Lm16jvBZ2VQf+RLmbd7wVUsALibYI/IQ=
|
||||
golang.org/x/tools v0.38.0/go.mod h1:yEsQ/d/YK8cjh0L6rZlY8tgtlKiBNTL14pGDJPJpYQs=
|
||||
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
google.golang.org/api v0.4.0/go.mod h1:8k5glujaEP+g9n7WNsDg8QP6cUVNI86fCNMcbazEtwE=
|
||||
google.golang.org/api v0.7.0/go.mod h1:WtwebWUNSVBH/HAw79HIFXZNqEvBhG+Ra+ax0hx3E3M=
|
||||
|
||||
@@ -27,7 +27,7 @@ func MustLogin(t *gotext.Locale, conf *koanf.Koanf, session *sessions.Manager, u
|
||||
"/api/user/logout",
|
||||
"/api/user/is_login",
|
||||
"/api/user/is_2fa",
|
||||
"/api/dashboard/panel",
|
||||
"/api/home/panel",
|
||||
}
|
||||
return func(next http.Handler) http.Handler {
|
||||
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
package request
|
||||
|
||||
type DashboardCurrent struct {
|
||||
type HomeCurrent struct {
|
||||
Nets []string `json:"nets" form:"nets"`
|
||||
Disks []string `json:"disks" form:"disks"`
|
||||
}
|
||||
@@ -19,7 +19,7 @@ type Http struct {
|
||||
conf *koanf.Koanf
|
||||
user *service.UserService
|
||||
userToken *service.UserTokenService
|
||||
dashboard *service.DashboardService
|
||||
home *service.HomeService
|
||||
task *service.TaskService
|
||||
website *service.WebsiteService
|
||||
database *service.DatabaseService
|
||||
@@ -53,7 +53,7 @@ func NewHttp(
|
||||
conf *koanf.Koanf,
|
||||
user *service.UserService,
|
||||
userToken *service.UserTokenService,
|
||||
dashboard *service.DashboardService,
|
||||
home *service.HomeService,
|
||||
task *service.TaskService,
|
||||
website *service.WebsiteService,
|
||||
database *service.DatabaseService,
|
||||
@@ -86,7 +86,7 @@ func NewHttp(
|
||||
conf: conf,
|
||||
user: user,
|
||||
userToken: userToken,
|
||||
dashboard: dashboard,
|
||||
home: home,
|
||||
task: task,
|
||||
website: website,
|
||||
database: database,
|
||||
@@ -146,17 +146,17 @@ func (route *Http) Register(r *chi.Mux) {
|
||||
r.Delete("/{id}", route.userToken.Delete)
|
||||
})
|
||||
|
||||
r.Route("/dashboard", func(r chi.Router) {
|
||||
r.Get("/panel", route.dashboard.Panel)
|
||||
r.Get("/home_apps", route.dashboard.HomeApps)
|
||||
r.Post("/current", route.dashboard.Current)
|
||||
r.Get("/system_info", route.dashboard.SystemInfo)
|
||||
r.Get("/count_info", route.dashboard.CountInfo)
|
||||
r.Get("/installed_db_and_php", route.dashboard.InstalledDbAndPhp)
|
||||
r.Get("/check_update", route.dashboard.CheckUpdate)
|
||||
r.Get("/update_info", route.dashboard.UpdateInfo)
|
||||
r.Post("/update", route.dashboard.Update)
|
||||
r.Post("/restart", route.dashboard.Restart)
|
||||
r.Route("/home", func(r chi.Router) {
|
||||
r.Get("/panel", route.home.Panel)
|
||||
r.Get("/apps", route.home.Apps)
|
||||
r.Post("/current", route.home.Current)
|
||||
r.Get("/system_info", route.home.SystemInfo)
|
||||
r.Get("/count_info", route.home.CountInfo)
|
||||
r.Get("/installed_db_and_php", route.home.InstalledDbAndPhp)
|
||||
r.Get("/check_update", route.home.CheckUpdate)
|
||||
r.Get("/update_info", route.home.UpdateInfo)
|
||||
r.Post("/update", route.home.Update)
|
||||
r.Post("/restart", route.home.Restart)
|
||||
})
|
||||
|
||||
r.Route("/task", func(r chi.Router) {
|
||||
|
||||
@@ -26,7 +26,7 @@ import (
|
||||
"github.com/acepanel/panel/pkg/types"
|
||||
)
|
||||
|
||||
type DashboardService struct {
|
||||
type HomeService struct {
|
||||
t *gotext.Locale
|
||||
api *api.API
|
||||
conf *koanf.Koanf
|
||||
@@ -38,8 +38,8 @@ type DashboardService struct {
|
||||
backupRepo biz.BackupRepo
|
||||
}
|
||||
|
||||
func NewDashboardService(t *gotext.Locale, conf *koanf.Koanf, task biz.TaskRepo, website biz.WebsiteRepo, appRepo biz.AppRepo, setting biz.SettingRepo, cron biz.CronRepo, backupRepo biz.BackupRepo) *DashboardService {
|
||||
return &DashboardService{
|
||||
func NewHomeService(t *gotext.Locale, conf *koanf.Koanf, task biz.TaskRepo, website biz.WebsiteRepo, appRepo biz.AppRepo, setting biz.SettingRepo, cron biz.CronRepo, backupRepo biz.BackupRepo) *HomeService {
|
||||
return &HomeService{
|
||||
t: t,
|
||||
api: api.NewAPI(app.Version, app.Locale),
|
||||
conf: conf,
|
||||
@@ -52,7 +52,7 @@ func NewDashboardService(t *gotext.Locale, conf *koanf.Koanf, task biz.TaskRepo,
|
||||
}
|
||||
}
|
||||
|
||||
func (s *DashboardService) Panel(w http.ResponseWriter, r *http.Request) {
|
||||
func (s *HomeService) Panel(w http.ResponseWriter, r *http.Request) {
|
||||
name, _ := s.settingRepo.Get(biz.SettingKeyName)
|
||||
if name == "" {
|
||||
name = s.t.Get("AcePanel")
|
||||
@@ -64,7 +64,7 @@ func (s *DashboardService) Panel(w http.ResponseWriter, r *http.Request) {
|
||||
})
|
||||
}
|
||||
|
||||
func (s *DashboardService) HomeApps(w http.ResponseWriter, r *http.Request) {
|
||||
func (s *HomeService) Apps(w http.ResponseWriter, r *http.Request) {
|
||||
apps, err := s.appRepo.GetHomeShow()
|
||||
if err != nil {
|
||||
Error(w, http.StatusInternalServerError, s.t.Get("failed to get home apps: %v", err))
|
||||
@@ -74,8 +74,8 @@ func (s *DashboardService) HomeApps(w http.ResponseWriter, r *http.Request) {
|
||||
Success(w, apps)
|
||||
}
|
||||
|
||||
func (s *DashboardService) Current(w http.ResponseWriter, r *http.Request) {
|
||||
req, err := Bind[request.DashboardCurrent](r)
|
||||
func (s *HomeService) Current(w http.ResponseWriter, r *http.Request) {
|
||||
req, err := Bind[request.HomeCurrent](r)
|
||||
if err != nil {
|
||||
Error(w, http.StatusUnprocessableEntity, "%v", err)
|
||||
return
|
||||
@@ -84,7 +84,7 @@ func (s *DashboardService) Current(w http.ResponseWriter, r *http.Request) {
|
||||
Success(w, tools.CurrentInfo(req.Nets, req.Disks))
|
||||
}
|
||||
|
||||
func (s *DashboardService) SystemInfo(w http.ResponseWriter, r *http.Request) {
|
||||
func (s *HomeService) SystemInfo(w http.ResponseWriter, r *http.Request) {
|
||||
hostInfo, err := host.Info()
|
||||
if err != nil {
|
||||
Error(w, http.StatusInternalServerError, s.t.Get("failed to get system info: %v", err))
|
||||
@@ -130,7 +130,7 @@ func (s *DashboardService) SystemInfo(w http.ResponseWriter, r *http.Request) {
|
||||
})
|
||||
}
|
||||
|
||||
func (s *DashboardService) CountInfo(w http.ResponseWriter, r *http.Request) {
|
||||
func (s *HomeService) CountInfo(w http.ResponseWriter, r *http.Request) {
|
||||
websiteCount, err := s.websiteRepo.Count()
|
||||
if err != nil {
|
||||
Error(w, http.StatusInternalServerError, s.t.Get("failed to get the total number of websites: %v", err))
|
||||
@@ -190,7 +190,7 @@ func (s *DashboardService) CountInfo(w http.ResponseWriter, r *http.Request) {
|
||||
})
|
||||
}
|
||||
|
||||
func (s *DashboardService) InstalledDbAndPhp(w http.ResponseWriter, r *http.Request) {
|
||||
func (s *HomeService) InstalledDbAndPhp(w http.ResponseWriter, r *http.Request) {
|
||||
mysqlInstalled, _ := s.appRepo.IsInstalled("slug = ?", "mysql")
|
||||
postgresqlInstalled, _ := s.appRepo.IsInstalled("slug = ?", "postgresql")
|
||||
php, _ := s.appRepo.GetInstalledAll("slug like ?", "php%")
|
||||
@@ -223,7 +223,7 @@ func (s *DashboardService) InstalledDbAndPhp(w http.ResponseWriter, r *http.Requ
|
||||
})
|
||||
}
|
||||
|
||||
func (s *DashboardService) CheckUpdate(w http.ResponseWriter, r *http.Request) {
|
||||
func (s *HomeService) CheckUpdate(w http.ResponseWriter, r *http.Request) {
|
||||
if offline, _ := s.settingRepo.GetBool(biz.SettingKeyOfflineMode); offline {
|
||||
Error(w, http.StatusForbidden, s.t.Get("unable to check for updates in offline mode"))
|
||||
return
|
||||
@@ -259,7 +259,7 @@ func (s *DashboardService) CheckUpdate(w http.ResponseWriter, r *http.Request) {
|
||||
})
|
||||
}
|
||||
|
||||
func (s *DashboardService) UpdateInfo(w http.ResponseWriter, r *http.Request) {
|
||||
func (s *HomeService) UpdateInfo(w http.ResponseWriter, r *http.Request) {
|
||||
if offline, _ := s.settingRepo.GetBool(biz.SettingKeyOfflineMode); offline {
|
||||
Error(w, http.StatusForbidden, s.t.Get("unable to check for updates in offline mode"))
|
||||
return
|
||||
@@ -297,7 +297,7 @@ func (s *DashboardService) UpdateInfo(w http.ResponseWriter, r *http.Request) {
|
||||
Success(w, versions)
|
||||
}
|
||||
|
||||
func (s *DashboardService) Update(w http.ResponseWriter, r *http.Request) {
|
||||
func (s *HomeService) Update(w http.ResponseWriter, r *http.Request) {
|
||||
if offline, _ := s.settingRepo.GetBool(biz.SettingKeyOfflineMode); offline {
|
||||
Error(w, http.StatusForbidden, s.t.Get("unable to update in offline mode"))
|
||||
return
|
||||
@@ -334,7 +334,7 @@ func (s *DashboardService) Update(w http.ResponseWriter, r *http.Request) {
|
||||
tools.RestartPanel()
|
||||
}
|
||||
|
||||
func (s *DashboardService) Restart(w http.ResponseWriter, r *http.Request) {
|
||||
func (s *HomeService) Restart(w http.ResponseWriter, r *http.Request) {
|
||||
if s.taskRepo.HasRunningTask() {
|
||||
Error(w, http.StatusInternalServerError, s.t.Get("background task is running, restart is prohibited, please try again later"))
|
||||
return
|
||||
@@ -16,12 +16,12 @@ var ProviderSet = wire.NewSet(
|
||||
NewContainerNetworkService,
|
||||
NewContainerVolumeService,
|
||||
NewCronService,
|
||||
NewDashboardService,
|
||||
NewDatabaseService,
|
||||
NewDatabaseServerService,
|
||||
NewDatabaseUserService,
|
||||
NewFileService,
|
||||
NewFirewallService,
|
||||
NewHomeService,
|
||||
NewMonitorService,
|
||||
NewProcessService,
|
||||
NewSafeService,
|
||||
|
||||
@@ -1,25 +0,0 @@
|
||||
import { http } from '@/utils'
|
||||
|
||||
export default {
|
||||
// 面板信息
|
||||
panel: (): any => http.Get('/dashboard/panel'),
|
||||
// 首页应用
|
||||
homeApps: (): any => http.Get('/dashboard/home_apps'),
|
||||
// 实时信息
|
||||
current: (nets: string[], disks: string[]): any =>
|
||||
http.Post('/dashboard/current', { nets, disks }, { meta: { noAlert: true } }),
|
||||
// 系统信息
|
||||
systemInfo: (): any => http.Get('/dashboard/system_info'),
|
||||
// 统计信息
|
||||
countInfo: (): any => http.Get('/dashboard/count_info'),
|
||||
// 已安装的数据库和PHP
|
||||
installedDbAndPhp: (): any => http.Get('/dashboard/installed_db_and_php'),
|
||||
// 检查更新
|
||||
checkUpdate: (): any => http.Get('/dashboard/check_update'),
|
||||
// 更新日志
|
||||
updateInfo: (): any => http.Get('/dashboard/update_info'),
|
||||
// 更新面板
|
||||
update: (): any => http.Post('/dashboard/update'),
|
||||
// 重启面板
|
||||
restart: (): any => http.Post('/dashboard/restart')
|
||||
}
|
||||
25
web/src/api/panel/home/index.ts
Normal file
25
web/src/api/panel/home/index.ts
Normal file
@@ -0,0 +1,25 @@
|
||||
import { http } from '@/utils'
|
||||
|
||||
export default {
|
||||
// 面板信息
|
||||
panel: (): any => http.Get('/home/panel'),
|
||||
// 首页应用
|
||||
apps: (): any => http.Get('/home/apps'),
|
||||
// 实时信息
|
||||
current: (nets: string[], disks: string[]): any =>
|
||||
http.Post('/home/current', { nets, disks }, { meta: { noAlert: true } }),
|
||||
// 系统信息
|
||||
systemInfo: (): any => http.Get('/home/system_info'),
|
||||
// 统计信息
|
||||
countInfo: (): any => http.Get('/home/count_info'),
|
||||
// 已安装的数据库和PHP
|
||||
installedDbAndPhp: (): any => http.Get('/home/installed_db_and_php'),
|
||||
// 检查更新
|
||||
checkUpdate: (): any => http.Get('/home/check_update'),
|
||||
// 更新日志
|
||||
updateInfo: (): any => http.Get('/home/update_info'),
|
||||
// 更新面板
|
||||
update: (): any => http.Post('/home/update'),
|
||||
// 重启面板
|
||||
restart: (): any => http.Post('/home/restart')
|
||||
}
|
||||
@@ -6,13 +6,13 @@ const themeStore = useThemeStore()
|
||||
const router = useRouter()
|
||||
const logo = computed(() => themeStore.logo || logoImg)
|
||||
|
||||
const toDashboard = () => {
|
||||
router.push({ name: 'dashboard' })
|
||||
const toHome = () => {
|
||||
router.push({ name: 'home' })
|
||||
}
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="h-60 f-c-c cursor-pointer" @click="toDashboard">
|
||||
<div class="h-60 f-c-c cursor-pointer" @click="toHome">
|
||||
<n-image :src="logo" height="32" preview-disabled />
|
||||
<h2
|
||||
v-show="!themeStore.sider.collapsed"
|
||||
|
||||
@@ -8,16 +8,17 @@ export function translateTitle(key: string): string {
|
||||
Backup: $gettext('Backup'),
|
||||
Certificate: $gettext('Certificate'),
|
||||
Container: $gettext('Container'),
|
||||
Dashboard: $gettext('Dashboard'),
|
||||
Update: $gettext('Update'),
|
||||
Database: $gettext('Database'),
|
||||
Files: $gettext('Files'),
|
||||
Firewall: $gettext('Firewall'),
|
||||
Home: $gettext('Home'),
|
||||
Monitoring: $gettext('Monitoring'),
|
||||
Settings: $gettext('Settings'),
|
||||
Project: $gettext('Project'),
|
||||
Setting: $gettext('Setting'),
|
||||
Terminal: $gettext('Terminal'),
|
||||
Tasks: $gettext('Tasks'),
|
||||
Task: $gettext('Task'),
|
||||
Toolbox: $gettext('Toolbox'),
|
||||
Update: $gettext('Update'),
|
||||
Website: $gettext('Website'),
|
||||
'Website Edit': $gettext('Website Edit'),
|
||||
// 应用标题
|
||||
|
||||
@@ -12,7 +12,7 @@ import { gettext, setCurrent, setupNaiveDiscreteApi } from '@/utils'
|
||||
|
||||
import { install as VueMonacoEditorPlugin } from '@guolao/vue-monaco-editor'
|
||||
|
||||
import dashboard from '@/api/panel/dashboard'
|
||||
import dashboard from '@/api/panel/home'
|
||||
import CronNaivePlugin from '@vue-js-cron/naive-ui'
|
||||
|
||||
async function setupApp() {
|
||||
|
||||
@@ -3,20 +3,37 @@ defineOptions({
|
||||
name: 'app-index'
|
||||
})
|
||||
|
||||
import { NButton } from 'naive-ui'
|
||||
import { useGettext } from 'vue3-gettext'
|
||||
|
||||
import app from '@/api/panel/app'
|
||||
import InstallView from '@/views/app/InstallView.vue'
|
||||
|
||||
const { $gettext } = useGettext()
|
||||
|
||||
const currentTab = ref('installed')
|
||||
|
||||
const handleUpdateCache = () => {
|
||||
useRequest(app.updateCache()).onSuccess(() => {
|
||||
window.$message.success($gettext('Cache updated successfully'))
|
||||
})
|
||||
}
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<common-page show-header show-footer>
|
||||
<template #tabbar>
|
||||
<n-tabs v-model:value="currentTab" animated>
|
||||
<n-tab name="installed" :tab="$gettext('Installed')" />
|
||||
<n-tab name="install" :tab="$gettext('Install')" />
|
||||
<n-tab name="environment" :tab="$gettext('Environment')" />
|
||||
<n-tab name="compose" :tab="$gettext('Compose Templates')" />
|
||||
</n-tabs>
|
||||
<div class="flex items-center justify-between">
|
||||
<n-tabs v-model:value="currentTab" animated class="flex-1">
|
||||
<n-tab name="installed" :tab="$gettext('Installed')" />
|
||||
<n-tab name="install" :tab="$gettext('Install')" />
|
||||
<n-tab name="environment" :tab="$gettext('Environment')" />
|
||||
<n-tab name="compose" :tab="$gettext('Compose Templates')" />
|
||||
</n-tabs>
|
||||
<n-button v-if="currentTab != 'installed'" type="primary" @click="handleUpdateCache">
|
||||
{{ $gettext('Update Cache') }}
|
||||
</n-button>
|
||||
</div>
|
||||
</template>
|
||||
<install-view v-if="currentTab === 'install'" />
|
||||
</common-page>
|
||||
|
||||
@@ -196,13 +196,6 @@ const handleManage = (slug: string) => {
|
||||
router.push({ name: 'apps-' + slug + '-index' })
|
||||
}
|
||||
|
||||
const handleUpdateCache = () => {
|
||||
useRequest(app.updateCache()).onSuccess(() => {
|
||||
refresh()
|
||||
window.$message.success($gettext('Cache updated successfully'))
|
||||
})
|
||||
}
|
||||
|
||||
onMounted(() => {
|
||||
refresh()
|
||||
})
|
||||
@@ -210,11 +203,6 @@ onMounted(() => {
|
||||
|
||||
<template>
|
||||
<n-flex vertical>
|
||||
<n-flex>
|
||||
<n-button type="primary" @click="handleUpdateCache">
|
||||
{{ $gettext('Update Cache') }}
|
||||
</n-button>
|
||||
</n-flex>
|
||||
<n-alert type="warning">{{
|
||||
$gettext(
|
||||
'Before updating apps, it is strongly recommended to backup/snapshot first, so you can roll back immediately if there are any issues!'
|
||||
|
||||
@@ -3,14 +3,14 @@ defineOptions({
|
||||
name: 'backup-index'
|
||||
})
|
||||
|
||||
import dashboard from '@/api/panel/dashboard'
|
||||
import home from '@/api/panel/home'
|
||||
import ListView from '@/views/backup/ListView.vue'
|
||||
import { useGettext } from 'vue3-gettext'
|
||||
|
||||
const { $gettext } = useGettext()
|
||||
const currentTab = ref('website')
|
||||
|
||||
const { data: installedDbAndPhp } = useRequest(dashboard.installedDbAndPhp, {
|
||||
const { data: installedDbAndPhp } = useRequest(home.installedDbAndPhp, {
|
||||
initialData: {
|
||||
db: [
|
||||
{
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
<script lang="ts" setup>
|
||||
defineOptions({
|
||||
name: 'dashboard-index'
|
||||
name: 'home-index'
|
||||
})
|
||||
|
||||
import { LineChart } from 'echarts/charts'
|
||||
@@ -16,7 +16,7 @@ import { CanvasRenderer } from 'echarts/renderers'
|
||||
import { NButton, NPopconfirm, useThemeVars } from 'naive-ui'
|
||||
import { useGettext } from 'vue3-gettext'
|
||||
|
||||
import dashboard from '@/api/panel/dashboard'
|
||||
import home from '@/api/panel/home'
|
||||
import { router } from '@/router'
|
||||
import { useTabStore } from '@/store'
|
||||
import { formatDateTime, formatDuration, toTimestamp } from '@/utils/common'
|
||||
@@ -39,7 +39,7 @@ const themeVars = useThemeVars()
|
||||
const tabStore = useTabStore()
|
||||
const realtime = ref<Realtime | null>(null)
|
||||
|
||||
const { data: systemInfo } = useRequest(dashboard.systemInfo, {
|
||||
const { data: systemInfo } = useRequest(home.systemInfo, {
|
||||
initialData: {
|
||||
procs: 0,
|
||||
hostname: '',
|
||||
@@ -59,7 +59,7 @@ const { data: systemInfo } = useRequest(dashboard.systemInfo, {
|
||||
disks: []
|
||||
}
|
||||
})
|
||||
const { data: homeApps, loading: homeAppsLoading } = useRequest(dashboard.homeApps, {
|
||||
const { data: apps, loading: appLoading } = useRequest(home.apps, {
|
||||
initialData: {
|
||||
description: '',
|
||||
icon: '',
|
||||
@@ -68,7 +68,7 @@ const { data: homeApps, loading: homeAppsLoading } = useRequest(dashboard.homeAp
|
||||
version: ''
|
||||
}
|
||||
})
|
||||
const { data: countInfo } = useRequest(dashboard.countInfo, {
|
||||
const { data: countInfo } = useRequest(home.countInfo, {
|
||||
initialData: {
|
||||
website: 0,
|
||||
database: 0,
|
||||
@@ -235,7 +235,7 @@ let isFetching = false
|
||||
const fetchCurrent = () => {
|
||||
if (isFetching) return
|
||||
isFetching = true
|
||||
useRequest(dashboard.current(nets.value, disks.value))
|
||||
useRequest(home.current(nets.value, disks.value))
|
||||
.onSuccess(({ data }) => {
|
||||
data.percent = formatPercent(data.percent)
|
||||
data.mem.usedPercent = formatPercent(data.mem.usedPercent)
|
||||
@@ -323,7 +323,7 @@ const fetchCurrent = () => {
|
||||
const handleRestartPanel = () => {
|
||||
clearInterval(homeInterval)
|
||||
window.$message.loading($gettext('Panel restarting...'))
|
||||
useRequest(dashboard.restart()).onSuccess(() => {
|
||||
useRequest(home.restart()).onSuccess(() => {
|
||||
window.$message.success($gettext('Panel restarted successfully'))
|
||||
setTimeout(() => {
|
||||
tabStore.reloadTab(tabStore.active)
|
||||
@@ -332,9 +332,9 @@ const handleRestartPanel = () => {
|
||||
}
|
||||
|
||||
const handleUpdate = () => {
|
||||
useRequest(dashboard.checkUpdate()).onSuccess(({ data }) => {
|
||||
useRequest(home.checkUpdate()).onSuccess(({ data }) => {
|
||||
if (data.update) {
|
||||
router.push({ name: 'dashboard-update' })
|
||||
router.push({ name: 'home-update' })
|
||||
} else {
|
||||
window.$message.success($gettext('Current version is the latest'))
|
||||
}
|
||||
@@ -682,7 +682,7 @@ if (import.meta.hot) {
|
||||
<n-card :segmented="true" size="small" :title="$gettext('Quick Apps')" min-h-340>
|
||||
<n-scrollbar max-h-270>
|
||||
<n-grid
|
||||
v-if="!homeAppsLoading"
|
||||
v-if="!appLoading"
|
||||
x-gap="12"
|
||||
y-gap="12"
|
||||
cols="3 s:1 m:2 l:3"
|
||||
@@ -690,7 +690,7 @@ if (import.meta.hot) {
|
||||
responsive="screen"
|
||||
p-10
|
||||
>
|
||||
<n-gi v-for="item in homeApps" :key="item.name">
|
||||
<n-gi v-for="item in apps" :key="item.name">
|
||||
<n-card
|
||||
:segmented="true"
|
||||
size="small"
|
||||
@@ -717,10 +717,10 @@ if (import.meta.hot) {
|
||||
</n-gi>
|
||||
</n-grid>
|
||||
</n-scrollbar>
|
||||
<n-text v-if="!homeAppsLoading && !homeApps.length">
|
||||
<n-text v-if="!appLoading && !apps.length">
|
||||
{{ $gettext('You have not set any apps to display here!') }}
|
||||
</n-text>
|
||||
<n-skeleton v-if="homeAppsLoading" text :repeat="12" />
|
||||
<n-skeleton v-if="appLoading" text :repeat="12" />
|
||||
</n-card>
|
||||
<n-card :segmented="true" size="small" :title="$gettext('Environment Information')">
|
||||
<n-table v-if="systemInfo" :single-line="false">
|
||||
@@ -1,6 +1,6 @@
|
||||
<script setup lang="ts">
|
||||
defineOptions({
|
||||
name: 'dashboard-update'
|
||||
name: 'home-update'
|
||||
})
|
||||
|
||||
import { MdPreview } from 'md-editor-v3'
|
||||
@@ -9,12 +9,12 @@ import type { MessageReactive } from 'naive-ui'
|
||||
import { NButton } from 'naive-ui'
|
||||
import { useGettext } from 'vue3-gettext'
|
||||
|
||||
import dashboard from '@/api/panel/dashboard'
|
||||
import home from '@/api/panel/home'
|
||||
import { router } from '@/router'
|
||||
import { formatDateTime } from '@/utils'
|
||||
|
||||
const { $gettext } = useGettext()
|
||||
const { data: versions } = useRequest(dashboard.updateInfo, {
|
||||
const { data: versions } = useRequest(home.updateInfo, {
|
||||
initialData: []
|
||||
})
|
||||
let messageReactive: MessageReactive | null = null
|
||||
@@ -29,13 +29,13 @@ const handleUpdate = () => {
|
||||
messageReactive = window.$message.loading($gettext('Panel updating...'), {
|
||||
duration: 0
|
||||
})
|
||||
useRequest(dashboard.update())
|
||||
useRequest(home.update())
|
||||
.onSuccess(() => {
|
||||
setTimeout(() => {
|
||||
setTimeout(() => {
|
||||
window.location.reload()
|
||||
}, 400)
|
||||
router.push({ name: 'dashboard-index' })
|
||||
router.push({ name: 'home-index' })
|
||||
}, 2500)
|
||||
window.$message.success($gettext('Panel updated successfully'))
|
||||
})
|
||||
@@ -3,27 +3,26 @@ import type { RouteType } from '~/types/router'
|
||||
const Layout = () => import('@/layout/IndexView.vue')
|
||||
|
||||
export default {
|
||||
name: 'dashboard',
|
||||
name: 'home',
|
||||
path: '/',
|
||||
component: Layout,
|
||||
redirect: '/dashboard',
|
||||
meta: {
|
||||
order: 0
|
||||
},
|
||||
children: [
|
||||
{
|
||||
name: 'dashboard-index',
|
||||
path: 'dashboard',
|
||||
name: 'home-index',
|
||||
path: '',
|
||||
component: () => import('./IndexView.vue'),
|
||||
meta: {
|
||||
title: 'Dashboard',
|
||||
icon: 'mdi:gauge',
|
||||
title: 'Home',
|
||||
icon: 'mdi:house-outline',
|
||||
role: ['admin'],
|
||||
requireAuth: true
|
||||
}
|
||||
},
|
||||
{
|
||||
name: 'dashboard-update',
|
||||
name: 'home-update',
|
||||
path: 'update',
|
||||
component: () => import('./UpdateView.vue'),
|
||||
isHidden: true,
|
||||
@@ -15,8 +15,8 @@ export default {
|
||||
path: '',
|
||||
component: () => import('./IndexView.vue'),
|
||||
meta: {
|
||||
title: 'Projects',
|
||||
icon: 'mdi:folder-multiple',
|
||||
title: 'Project',
|
||||
icon: 'mdi:folder-multiple-outline',
|
||||
role: ['admin'],
|
||||
requireAuth: true
|
||||
}
|
||||
|
||||
@@ -15,7 +15,7 @@ export default {
|
||||
path: '',
|
||||
component: () => import('./IndexView.vue'),
|
||||
meta: {
|
||||
title: 'Settings',
|
||||
title: 'Setting',
|
||||
icon: 'mdi:settings-outline',
|
||||
role: ['admin'],
|
||||
requireAuth: true
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
<script setup lang="ts">
|
||||
import app from '@/api/panel/app'
|
||||
import cron from '@/api/panel/cron'
|
||||
import dashboard from '@/api/panel/dashboard'
|
||||
import dashboard from '@/api/panel/home'
|
||||
import website from '@/api/panel/website'
|
||||
import Editor from '@guolao/vue-monaco-editor'
|
||||
import { CronNaive } from '@vue-js-cron/naive-ui'
|
||||
|
||||
@@ -5,7 +5,6 @@ defineOptions({
|
||||
|
||||
import CreateModal from '@/views/task/CreateModal.vue'
|
||||
import CronView from '@/views/task/CronView.vue'
|
||||
import SystemView from '@/views/task/SystemView.vue'
|
||||
import TaskView from '@/views/task/TaskView.vue'
|
||||
import { NButton } from 'naive-ui'
|
||||
import { useGettext } from 'vue3-gettext'
|
||||
@@ -21,7 +20,6 @@ const create = ref(false)
|
||||
<template #tabbar>
|
||||
<n-tabs v-model:value="current" animated>
|
||||
<n-tab name="cron" :tab="$gettext('Scheduled Tasks')" />
|
||||
<n-tab name="system" :tab="$gettext('System Processes')" />
|
||||
<n-tab name="task" :tab="$gettext('Panel Tasks')" />
|
||||
</n-tabs>
|
||||
</template>
|
||||
@@ -32,7 +30,6 @@ const create = ref(false)
|
||||
</n-button>
|
||||
</n-flex>
|
||||
<cron-view v-if="current === 'cron'" />
|
||||
<system-view v-if="current === 'system'" />
|
||||
<task-view v-if="current === 'task'" />
|
||||
</n-flex>
|
||||
</common-page>
|
||||
|
||||
@@ -15,7 +15,7 @@ export default {
|
||||
path: '',
|
||||
component: () => import('./IndexView.vue'),
|
||||
meta: {
|
||||
title: 'Tasks',
|
||||
title: 'Task',
|
||||
icon: 'mdi:timetable',
|
||||
role: ['admin'],
|
||||
requireAuth: true
|
||||
|
||||
@@ -4,22 +4,25 @@ defineOptions({
|
||||
})
|
||||
|
||||
import BenchmarkView from '@/views/toolbox/BenchmarkView.vue'
|
||||
import ProcessView from '@/views/toolbox/ProcessView.vue'
|
||||
import SystemView from '@/views/toolbox/SystemView.vue'
|
||||
import { useGettext } from 'vue3-gettext'
|
||||
|
||||
const { $gettext } = useGettext()
|
||||
const current = ref('system')
|
||||
const current = ref('process')
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<common-page show-header show-footer>
|
||||
<template #tabbar>
|
||||
<n-tabs v-model:value="current" animated>
|
||||
<n-tab name="process" :tab="$gettext('Process')" />
|
||||
<n-tab name="system" :tab="$gettext('System')" />
|
||||
<n-tab name="benchmark" :tab="$gettext('Benchmark')" />
|
||||
</n-tabs>
|
||||
</template>
|
||||
<n-flex vertical>
|
||||
<process-view v-if="current === 'process'" />
|
||||
<system-view v-if="current === 'system'" />
|
||||
<benchmark-view v-if="current === 'benchmark'" />
|
||||
</n-flex>
|
||||
|
||||
171
web/src/views/toolbox/ProcessView.vue
Normal file
171
web/src/views/toolbox/ProcessView.vue
Normal file
@@ -0,0 +1,171 @@
|
||||
<script setup lang="ts">
|
||||
import { NButton, NDataTable, NPopconfirm, NTag } from 'naive-ui'
|
||||
import { useGettext } from 'vue3-gettext'
|
||||
|
||||
import process from '@/api/panel/process'
|
||||
import { formatBytes, formatDateTime, formatPercent } from '@/utils'
|
||||
|
||||
const { $gettext } = useGettext()
|
||||
|
||||
const columns: any = [
|
||||
{
|
||||
title: 'PID',
|
||||
key: 'pid',
|
||||
width: 120,
|
||||
ellipsis: { tooltip: true }
|
||||
},
|
||||
{
|
||||
title: $gettext('Name'),
|
||||
key: 'name',
|
||||
minWidth: 250,
|
||||
resizable: true,
|
||||
ellipsis: { tooltip: true }
|
||||
},
|
||||
{
|
||||
title: $gettext('Parent PID'),
|
||||
key: 'ppid',
|
||||
width: 120,
|
||||
ellipsis: { tooltip: true }
|
||||
},
|
||||
{
|
||||
title: $gettext('Threads'),
|
||||
key: 'num_threads',
|
||||
width: 100,
|
||||
ellipsis: { tooltip: true }
|
||||
},
|
||||
{
|
||||
title: $gettext('User'),
|
||||
key: 'username',
|
||||
minWidth: 100,
|
||||
ellipsis: { tooltip: true }
|
||||
},
|
||||
{
|
||||
title: $gettext('Status'),
|
||||
key: 'status',
|
||||
minWidth: 150,
|
||||
ellipsis: { tooltip: true },
|
||||
render(row: any) {
|
||||
switch (row.status) {
|
||||
case 'R':
|
||||
return h(NTag, { type: 'success' }, { default: () => $gettext('Running') })
|
||||
case 'S':
|
||||
return h(NTag, { type: 'warning' }, { default: () => $gettext('Sleeping') })
|
||||
case 'T':
|
||||
return h(NTag, { type: 'error' }, { default: () => $gettext('Stopped') })
|
||||
case 'I':
|
||||
return h(NTag, { type: 'primary' }, { default: () => $gettext('Idle') })
|
||||
case 'Z':
|
||||
return h(NTag, { type: 'error' }, { default: () => $gettext('Zombie') })
|
||||
case 'W':
|
||||
return h(NTag, { type: 'warning' }, { default: () => $gettext('Waiting') })
|
||||
case 'L':
|
||||
return h(NTag, { type: 'info' }, { default: () => $gettext('Locked') })
|
||||
default:
|
||||
return h(NTag, { type: 'default' }, { default: () => row.status })
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
title: 'CPU',
|
||||
key: 'cpu',
|
||||
minWidth: 100,
|
||||
ellipsis: { tooltip: true },
|
||||
render(row: any): string {
|
||||
return formatPercent(row.cpu) + '%'
|
||||
}
|
||||
},
|
||||
{
|
||||
title: $gettext('Memory'),
|
||||
key: 'rss',
|
||||
minWidth: 100,
|
||||
ellipsis: { tooltip: true },
|
||||
render(row: any): string {
|
||||
return formatBytes(row.rss)
|
||||
}
|
||||
},
|
||||
{
|
||||
title: $gettext('Start Time'),
|
||||
key: 'start_time',
|
||||
width: 160,
|
||||
ellipsis: { tooltip: true },
|
||||
render(row: any): string {
|
||||
return formatDateTime(row.start_time)
|
||||
}
|
||||
},
|
||||
{
|
||||
title: $gettext('Actions'),
|
||||
key: 'actions',
|
||||
width: 150,
|
||||
hideInExcel: true,
|
||||
render(row: any) {
|
||||
return h(
|
||||
NPopconfirm,
|
||||
{
|
||||
onPositiveClick: () => {
|
||||
useRequest(process.kill(row.pid)).onSuccess(() => {
|
||||
refresh()
|
||||
window.$message.success(
|
||||
$gettext('Process %{ pid } has been terminated', { pid: row.pid })
|
||||
)
|
||||
})
|
||||
}
|
||||
},
|
||||
{
|
||||
default: () => {
|
||||
return $gettext('Are you sure you want to terminate process %{ pid }?', {
|
||||
pid: row.pid
|
||||
})
|
||||
},
|
||||
trigger: () => {
|
||||
return h(
|
||||
NButton,
|
||||
{
|
||||
size: 'small',
|
||||
type: 'error'
|
||||
},
|
||||
{
|
||||
default: () => $gettext('Terminate')
|
||||
}
|
||||
)
|
||||
}
|
||||
}
|
||||
)
|
||||
}
|
||||
}
|
||||
]
|
||||
|
||||
const { loading, data, page, total, pageSize, pageCount, refresh } = usePagination(
|
||||
(page, pageSize) => process.list(page, pageSize),
|
||||
{
|
||||
initialData: { total: 0, list: [] },
|
||||
initialPageSize: 20,
|
||||
total: (res: any) => res.total,
|
||||
data: (res: any) => res.items
|
||||
}
|
||||
)
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<n-flex vertical>
|
||||
<n-data-table
|
||||
striped
|
||||
remote
|
||||
:scroll-x="1400"
|
||||
:loading="loading"
|
||||
:columns="columns"
|
||||
:data="data"
|
||||
:row-key="(row: any) => row.pid"
|
||||
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-flex>
|
||||
</template>
|
||||
@@ -9,7 +9,7 @@ import { NButton } from 'naive-ui'
|
||||
import { useGettext } from 'vue3-gettext'
|
||||
|
||||
import cert from '@/api/panel/cert'
|
||||
import dashboard from '@/api/panel/dashboard'
|
||||
import dashboard from '@/api/panel/home'
|
||||
import website from '@/api/panel/website'
|
||||
import ProxyBuilderModal from '@/views/website/ProxyBuilderModal.vue'
|
||||
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
import { NButton, NCheckbox, NDataTable, NFlex, NInput, NPopconfirm, NSwitch, NTag } from 'naive-ui'
|
||||
import { useGettext } from 'vue3-gettext'
|
||||
|
||||
import dashboard from '@/api/panel/dashboard'
|
||||
import dashboard from '@/api/panel/home'
|
||||
import website from '@/api/panel/website'
|
||||
import { useFileStore } from '@/store'
|
||||
import { generateRandomString, isNullOrUndef } from '@/utils'
|
||||
|
||||
Reference in New Issue
Block a user