2
0
mirror of https://github.com/acepanel/panel.git synced 2026-02-04 06:47:20 +08:00

feat: 一堆调整

This commit is contained in:
2025-12-01 19:37:19 +08:00
parent a64a1ba5c8
commit 5fdce07190
28 changed files with 304 additions and 122 deletions

View File

@@ -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
View File

@@ -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=

View File

@@ -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) {

View File

@@ -1,6 +1,6 @@
package request
type DashboardCurrent struct {
type HomeCurrent struct {
Nets []string `json:"nets" form:"nets"`
Disks []string `json:"disks" form:"disks"`
}

View File

@@ -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) {

View File

@@ -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

View File

@@ -16,12 +16,12 @@ var ProviderSet = wire.NewSet(
NewContainerNetworkService,
NewContainerVolumeService,
NewCronService,
NewDashboardService,
NewDatabaseService,
NewDatabaseServerService,
NewDatabaseUserService,
NewFileService,
NewFirewallService,
NewHomeService,
NewMonitorService,
NewProcessService,
NewSafeService,

View File

@@ -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')
}

View 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')
}

View File

@@ -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"

View File

@@ -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'),
// 应用标题

View File

@@ -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() {

View File

@@ -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>

View File

@@ -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!'

View File

@@ -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: [
{

View File

@@ -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">

View File

@@ -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'))
})

View File

@@ -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,

View File

@@ -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
}

View File

@@ -15,7 +15,7 @@ export default {
path: '',
component: () => import('./IndexView.vue'),
meta: {
title: 'Settings',
title: 'Setting',
icon: 'mdi:settings-outline',
role: ['admin'],
requireAuth: true

View File

@@ -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'

View File

@@ -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>

View File

@@ -15,7 +15,7 @@ export default {
path: '',
component: () => import('./IndexView.vue'),
meta: {
title: 'Tasks',
title: 'Task',
icon: 'mdi:timetable',
role: ['admin'],
requireAuth: true

View File

@@ -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>

View 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>

View File

@@ -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'

View File

@@ -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'