mirror of
https://github.com/acepanel/panel.git
synced 2026-02-04 10:17:17 +08:00
feat: 重构选项卡样式
This commit is contained in:
@@ -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 />
|
||||
<app-footer v-if="showFooter" mt-15 />
|
||||
<app-footer v-if="showFooter" mt-auto pt-20 />
|
||||
</section>
|
||||
</transition>
|
||||
</template>
|
||||
|
||||
@@ -1,6 +1,4 @@
|
||||
<script lang="ts" setup>
|
||||
import { translateTitle } from '@/locales/menu'
|
||||
|
||||
interface Props {
|
||||
showFooter?: boolean
|
||||
showHeader?: boolean
|
||||
@@ -9,32 +7,23 @@ interface Props {
|
||||
|
||||
withDefaults(defineProps<Props>(), {
|
||||
showFooter: false,
|
||||
showHeader: true,
|
||||
showHeader: false,
|
||||
title: undefined
|
||||
})
|
||||
|
||||
const route = useRoute()
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<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>
|
||||
<div flex items-center>
|
||||
<slot v-if="$slots['title-prefix']" name="title-prefix" />
|
||||
<div mr-12 h-16 w-4 rounded-l-2 bg-primary></div>
|
||||
<h2 font-normal>
|
||||
{{ title ? title : route.meta.title ? translateTitle(route.meta.title) : '' }}
|
||||
</h2>
|
||||
<slot name="title-suffix" />
|
||||
</div>
|
||||
<slot name="action" />
|
||||
</template>
|
||||
</header>
|
||||
|
||||
<n-card flex-1>
|
||||
<slot />
|
||||
</n-card>
|
||||
<div class="flex flex-col gap-10">
|
||||
<header v-if="showHeader">
|
||||
<slot v-if="$slots.header" name="header" />
|
||||
<n-card v-else size="small">
|
||||
<slot name="tabbar" />
|
||||
</n-card>
|
||||
</header>
|
||||
<n-card>
|
||||
<slot />
|
||||
</n-card>
|
||||
</div>
|
||||
</app-page>
|
||||
</template>
|
||||
|
||||
@@ -3,11 +3,16 @@ import logoImg from '@/assets/images/logo.png'
|
||||
import { useThemeStore } from '@/store'
|
||||
|
||||
const themeStore = useThemeStore()
|
||||
const router = useRouter()
|
||||
const logo = computed(() => themeStore.logo || logoImg)
|
||||
|
||||
const toDashboard = () => {
|
||||
router.push({ name: 'dashboard' })
|
||||
}
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<router-link class="h-60 f-c-c" to="/">
|
||||
<div class="h-60 f-c-c cursor-pointer" @click="toDashboard">
|
||||
<n-image :src="logo" height="32" preview-disabled />
|
||||
<h2
|
||||
v-show="!themeStore.sider.collapsed"
|
||||
@@ -15,5 +20,5 @@ const logo = computed(() => themeStore.logo || logoImg)
|
||||
>
|
||||
{{ themeStore.name }}
|
||||
</h2>
|
||||
</router-link>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
@@ -65,44 +65,44 @@ const menus = computed<TreeSelectOption[]>(() => {
|
||||
</template>
|
||||
{{ $gettext('Menu Settings') }}
|
||||
</n-tooltip>
|
||||
<n-modal
|
||||
v-model:show="settingModal"
|
||||
preset="card"
|
||||
:title="$gettext('Menu Settings')"
|
||||
style="width: 60vw"
|
||||
size="huge"
|
||||
:bordered="false"
|
||||
:segmented="false"
|
||||
@close="settingModal = false"
|
||||
@mask-click="settingModal = false"
|
||||
>
|
||||
<n-form>
|
||||
<n-flex vertical>
|
||||
<n-alert type="info">
|
||||
{{
|
||||
$gettext(
|
||||
'Settings are saved in the browser and will be reset after clearing the browser cache'
|
||||
)
|
||||
}}
|
||||
</n-alert>
|
||||
<n-form-item :label="$gettext('Custom Logo')">
|
||||
<n-input
|
||||
v-model:value="themeStore.logo"
|
||||
:placeholder="$gettext('Please enter the complete URL')"
|
||||
/>
|
||||
</n-form-item>
|
||||
<n-form-item :label="$gettext('Hide Menu')">
|
||||
<n-tree-select
|
||||
cascade
|
||||
checkable
|
||||
clearable
|
||||
multiple
|
||||
:options="menus"
|
||||
v-model:value="permissionStore.hiddenRoutes"
|
||||
></n-tree-select>
|
||||
</n-form-item>
|
||||
</n-flex>
|
||||
</n-form>
|
||||
</n-modal>
|
||||
</div>
|
||||
<n-modal
|
||||
v-model:show="settingModal"
|
||||
preset="card"
|
||||
:title="$gettext('Menu Settings')"
|
||||
style="width: 60vw"
|
||||
size="huge"
|
||||
:bordered="false"
|
||||
:segmented="false"
|
||||
@close="settingModal = false"
|
||||
@mask-click="settingModal = false"
|
||||
>
|
||||
<n-form>
|
||||
<n-flex vertical>
|
||||
<n-alert type="info">
|
||||
{{
|
||||
$gettext(
|
||||
'Settings are saved in the browser and will be reset after clearing the browser cache'
|
||||
)
|
||||
}}
|
||||
</n-alert>
|
||||
<n-form-item :label="$gettext('Custom Logo')">
|
||||
<n-input
|
||||
v-model:value="themeStore.logo"
|
||||
:placeholder="$gettext('Please enter the complete URL')"
|
||||
/>
|
||||
</n-form-item>
|
||||
<n-form-item :label="$gettext('Hide Menu')">
|
||||
<n-tree-select
|
||||
cascade
|
||||
checkable
|
||||
clearable
|
||||
multiple
|
||||
:options="menus"
|
||||
v-model:value="permissionStore.hiddenRoutes"
|
||||
/>
|
||||
</n-form-item>
|
||||
</n-flex>
|
||||
</n-form>
|
||||
</n-modal>
|
||||
</template>
|
||||
|
||||
@@ -31,19 +31,14 @@ const postgreSQLInstalled = computed(() => {
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<common-page show-footer>
|
||||
<n-flex vertical>
|
||||
<n-tabs v-model:value="currentTab" type="line" animated>
|
||||
<n-tab-pane name="website" :tab="$gettext('Website')">
|
||||
<list-view v-model:type="currentTab" />
|
||||
</n-tab-pane>
|
||||
<n-tab-pane v-if="mySQLInstalled" name="mysql" tab="MySQL">
|
||||
<list-view v-model:type="currentTab" />
|
||||
</n-tab-pane>
|
||||
<n-tab-pane v-if="postgreSQLInstalled" name="postgres" tab="PostgreSQL">
|
||||
<list-view v-model:type="currentTab" />
|
||||
</n-tab-pane>
|
||||
<common-page show-header show-footer>
|
||||
<template #tabbar>
|
||||
<n-tabs v-model:value="currentTab" animated>
|
||||
<n-tab name="website" :tab="$gettext('Website')" />
|
||||
<n-tab v-if="mySQLInstalled" name="mysql" tab="MySQL" />
|
||||
<n-tab v-if="postgreSQLInstalled" name="postgres" tab="PostgreSQL" />
|
||||
</n-tabs>
|
||||
</n-flex>
|
||||
</template>
|
||||
<list-view v-model:type="currentTab" />
|
||||
</common-page>
|
||||
</template>
|
||||
|
||||
@@ -149,6 +149,21 @@ const handleDelete = async (file: string) => {
|
||||
})
|
||||
}
|
||||
|
||||
watch(
|
||||
type,
|
||||
(newType) => {
|
||||
if (newType === 'website') {
|
||||
createModel.value.target = websites.value[0]?.value || ''
|
||||
restoreModel.value.target = websites.value[0]?.value || ''
|
||||
} else {
|
||||
createModel.value.target = ''
|
||||
restoreModel.value.target = ''
|
||||
}
|
||||
refresh()
|
||||
},
|
||||
{ immediate: true }
|
||||
)
|
||||
|
||||
onMounted(() => {
|
||||
useRequest(app.isInstalled('nginx')).onSuccess(({ data }) => {
|
||||
if (data.installed) {
|
||||
|
||||
@@ -90,8 +90,15 @@ onUnmounted(() => {
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<common-page show-footer>
|
||||
<template #action>
|
||||
<common-page show-header show-footer>
|
||||
<template #tabbar>
|
||||
<n-tabs v-model:value="currentTab" animated>
|
||||
<n-tab name="cert" :tab="$gettext('Certificate List')" />
|
||||
<n-tab name="account" :tab="$gettext('Account List')" />
|
||||
<n-tab name="dns" :tab="$gettext('DNS List')" />
|
||||
</n-tabs>
|
||||
</template>
|
||||
<n-flex vertical>
|
||||
<n-flex>
|
||||
<n-button v-if="currentTab == 'cert'" type="success" @click="uploadCert = true">
|
||||
<the-icon :size="18" icon="material-symbols:upload" />
|
||||
@@ -101,7 +108,7 @@ onUnmounted(() => {
|
||||
<the-icon :size="18" icon="material-symbols:add" />
|
||||
{{ $gettext('Create Certificate') }}
|
||||
</n-button>
|
||||
<n-button v-if="currentTab == 'user'" type="primary" @click="createAccount = true">
|
||||
<n-button v-if="currentTab == 'account'" type="primary" @click="createAccount = true">
|
||||
<the-icon :size="18" icon="material-symbols:add" />
|
||||
{{ $gettext('Create Account') }}
|
||||
</n-button>
|
||||
@@ -110,18 +117,20 @@ onUnmounted(() => {
|
||||
{{ $gettext('Create DNS') }}
|
||||
</n-button>
|
||||
</n-flex>
|
||||
</template>
|
||||
<n-tabs v-model:value="currentTab" type="line" animated>
|
||||
<n-tab-pane name="cert" :tab="$gettext('Certificate List')">
|
||||
<cert-view :accounts="accounts" :algorithms="algorithms" :websites="websites" :dns="dns" />
|
||||
</n-tab-pane>
|
||||
<n-tab-pane name="user" :tab="$gettext('Account List')">
|
||||
<account-view :ca-providers="caProviders" :algorithms="algorithms" />
|
||||
</n-tab-pane>
|
||||
<n-tab-pane name="dns" :tab="$gettext('DNS List')">
|
||||
<dns-view :dns-providers="dnsProviders" />
|
||||
</n-tab-pane>
|
||||
</n-tabs>
|
||||
<cert-view
|
||||
v-if="currentTab == 'cert'"
|
||||
:accounts="accounts"
|
||||
:algorithms="algorithms"
|
||||
:websites="websites"
|
||||
:dns="dns"
|
||||
/>
|
||||
<account-view
|
||||
v-if="currentTab == 'account'"
|
||||
:ca-providers="caProviders"
|
||||
:algorithms="algorithms"
|
||||
/>
|
||||
<dns-view v-if="currentTab == 'dns'" :dns-providers="dnsProviders" />
|
||||
</n-flex>
|
||||
</common-page>
|
||||
<upload-cert-modal v-model:show="uploadCert" />
|
||||
<create-cert-modal
|
||||
|
||||
@@ -16,23 +16,20 @@ const current = ref('container')
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<common-page show-footer>
|
||||
<n-tabs v-model:value="current" type="line" animated>
|
||||
<n-tab-pane name="container" :tab="$gettext('Containers')">
|
||||
<container-view />
|
||||
</n-tab-pane>
|
||||
<n-tab-pane name="compose" :tab="$gettext('Compose')">
|
||||
<compose-view />
|
||||
</n-tab-pane>
|
||||
<n-tab-pane name="image" :tab="$gettext('Images')">
|
||||
<image-view />
|
||||
</n-tab-pane>
|
||||
<n-tab-pane name="network" :tab="$gettext('Networks')">
|
||||
<network-view />
|
||||
</n-tab-pane>
|
||||
<n-tab-pane name="volume" :tab="$gettext('Volumes')">
|
||||
<volume-view />
|
||||
</n-tab-pane>
|
||||
</n-tabs>
|
||||
<common-page show-header show-footer>
|
||||
<template #tabbar>
|
||||
<n-tabs v-model:value="current" animated>
|
||||
<n-tab name="container" :tab="$gettext('Containers')" />
|
||||
<n-tab name="compose" :tab="$gettext('Compose')" />
|
||||
<n-tab name="image" :tab="$gettext('Images')" />
|
||||
<n-tab name="network" :tab="$gettext('Networks')" />
|
||||
<n-tab name="volume" :tab="$gettext('Volumes')" />
|
||||
</n-tabs>
|
||||
</template>
|
||||
<container-view v-if="current === 'container'" />
|
||||
<compose-view v-else-if="current === 'compose'" />
|
||||
<image-view v-else-if="current === 'image'" />
|
||||
<network-view v-else-if="current === 'network'" />
|
||||
<volume-view v-else-if="current === 'volume'" />
|
||||
</common-page>
|
||||
</template>
|
||||
|
||||
@@ -21,37 +21,40 @@ const createServerModalShow = ref(false)
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<common-page show-footer>
|
||||
<template #action>
|
||||
<n-button
|
||||
v-if="currentTab === 'database'"
|
||||
type="primary"
|
||||
@click="createDatabaseModalShow = true"
|
||||
>
|
||||
<the-icon :size="18" icon="material-symbols:add" />
|
||||
{{ $gettext('Create Database') }}
|
||||
</n-button>
|
||||
<n-button v-if="currentTab === 'user'" type="primary" @click="createUserModalShow = true">
|
||||
<the-icon :size="18" icon="material-symbols:add" />
|
||||
{{ $gettext('Create User') }}
|
||||
</n-button>
|
||||
<n-button v-if="currentTab === 'server'" type="primary" @click="createServerModalShow = true">
|
||||
<the-icon :size="18" icon="material-symbols:add" />
|
||||
{{ $gettext('Add Server') }}
|
||||
</n-button>
|
||||
<common-page show-header show-footer>
|
||||
<template #tabbar>
|
||||
<n-tabs v-model:value="currentTab" animated>
|
||||
<n-tab name="database" :tab="$gettext('Database')" />
|
||||
<n-tab name="user" :tab="$gettext('User')" />
|
||||
<n-tab name="server" :tab="$gettext('Server')" />
|
||||
</n-tabs>
|
||||
</template>
|
||||
<n-flex vertical>
|
||||
<n-tabs v-model:value="currentTab" type="line" animated>
|
||||
<n-tab-pane name="database" :tab="$gettext('Database')">
|
||||
<database-list />
|
||||
</n-tab-pane>
|
||||
<n-tab-pane name="user" :tab="$gettext('User')">
|
||||
<user-list />
|
||||
</n-tab-pane>
|
||||
<n-tab-pane name="server" :tab="$gettext('Server')">
|
||||
<server-list />
|
||||
</n-tab-pane>
|
||||
</n-tabs>
|
||||
<n-flex>
|
||||
<n-button
|
||||
v-if="currentTab === 'database'"
|
||||
type="primary"
|
||||
@click="createDatabaseModalShow = true"
|
||||
>
|
||||
<the-icon :size="18" icon="material-symbols:add" />
|
||||
{{ $gettext('Create Database') }}
|
||||
</n-button>
|
||||
<n-button v-if="currentTab === 'user'" type="primary" @click="createUserModalShow = true">
|
||||
<the-icon :size="18" icon="material-symbols:add" />
|
||||
{{ $gettext('Create User') }}
|
||||
</n-button>
|
||||
<n-button
|
||||
v-if="currentTab === 'server'"
|
||||
type="primary"
|
||||
@click="createServerModalShow = true"
|
||||
>
|
||||
<the-icon :size="18" icon="material-symbols:add" />
|
||||
{{ $gettext('Add Server') }}
|
||||
</n-button>
|
||||
</n-flex>
|
||||
<database-list v-if="currentTab === 'database'" />
|
||||
<user-list v-if="currentTab === 'user'" />
|
||||
<server-list v-if="currentTab === 'server'" />
|
||||
</n-flex>
|
||||
</common-page>
|
||||
<create-database-modal v-model:show="createDatabaseModalShow" />
|
||||
|
||||
@@ -14,21 +14,19 @@ const currentTab = ref('rule')
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<common-page show-footer>
|
||||
<n-tabs v-model:value="currentTab" type="line" animated>
|
||||
<n-tab-pane name="rule" :tab="$gettext('Port Rules')">
|
||||
<rule-view />
|
||||
</n-tab-pane>
|
||||
<n-tab-pane name="ip-rule" :tab="$gettext('IP Rules')">
|
||||
<ip-rule-view />
|
||||
</n-tab-pane>
|
||||
<n-tab-pane name="forward" :tab="$gettext('Port Forwarding')">
|
||||
<forward-view />
|
||||
</n-tab-pane>
|
||||
<n-tab-pane name="setting" :tab="$gettext('Settings')">
|
||||
<setting-view />
|
||||
</n-tab-pane>
|
||||
</n-tabs>
|
||||
<common-page show-header show-footer>
|
||||
<template #tabbar>
|
||||
<n-tabs v-model:value="currentTab" animated>
|
||||
<n-tab name="rule" :tab="$gettext('Port Rules')" />
|
||||
<n-tab name="ip-rule" :tab="$gettext('IP Rules')" />
|
||||
<n-tab name="forward" :tab="$gettext('Port Forwarding')" />
|
||||
<n-tab name="setting" :tab="$gettext('Settings')" />
|
||||
</n-tabs>
|
||||
</template>
|
||||
<rule-view v-if="currentTab === 'rule'" />
|
||||
<ip-rule-view v-if="currentTab === 'ip-rule'" />
|
||||
<forward-view v-if="currentTab === 'forward'" />
|
||||
<setting-view v-if="currentTab === 'setting'" />
|
||||
</common-page>
|
||||
</template>
|
||||
|
||||
|
||||
@@ -442,45 +442,44 @@ watch(data, () => {
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<common-page show-footer>
|
||||
<template #action>
|
||||
<n-popconfirm @positive-click="handleClear">
|
||||
<template #trigger>
|
||||
<n-button type="error">
|
||||
<the-icon :size="18" icon="material-symbols:delete-outline" />
|
||||
{{ $gettext('Clear Monitoring Records') }}
|
||||
</n-button>
|
||||
</template>
|
||||
{{ $gettext('Are you sure you want to clear?') }}
|
||||
</n-popconfirm>
|
||||
</template>
|
||||
<n-card :segmented="true" flex items-center>
|
||||
<n-form
|
||||
inline
|
||||
label-placement="left"
|
||||
label-width="auto"
|
||||
require-mark-placement="right-hanging"
|
||||
>
|
||||
<n-flex items-center>
|
||||
<n-form-item :label="$gettext('Enable Monitoring')">
|
||||
<common-page show-header show-footer>
|
||||
<template #tabbar>
|
||||
<div class="flex items-center justify-between gap-8 py-4">
|
||||
<div class="flex items-center gap-6">
|
||||
<div class="flex items-center gap-10">
|
||||
{{ $gettext('Enable Monitoring') }}
|
||||
<n-switch v-model:value="monitorSwitch" @update-value="handleUpdate" />
|
||||
</n-form-item>
|
||||
<n-form-item :label="$gettext('Save Days')">
|
||||
</div>
|
||||
<div class="flex items-center gap-10 pl-20">
|
||||
{{ $gettext('Save Days') }}
|
||||
<n-input-number v-model:value="saveDay">
|
||||
<template #suffix> {{ $gettext('days') }} </template>
|
||||
</n-input-number>
|
||||
</n-form-item>
|
||||
<n-form-item>
|
||||
</div>
|
||||
<div>
|
||||
<n-button type="primary" @click="handleUpdate">{{ $gettext('Confirm') }}</n-button>
|
||||
</n-form-item>
|
||||
<n-form-item :label="$gettext('Time Selection')">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="flex items-center gap-10">
|
||||
<span>{{ $gettext('Time Selection') }}</span>
|
||||
<div class="flex items-center gap-2">
|
||||
<n-date-picker v-model:value="start" type="datetime" />
|
||||
-
|
||||
<span class="mx-1">-</span>
|
||||
<n-date-picker v-model:value="end" type="datetime" />
|
||||
</n-form-item>
|
||||
</n-flex>
|
||||
</n-form>
|
||||
</n-card>
|
||||
</div>
|
||||
<n-popconfirm @positive-click="handleClear">
|
||||
<template #trigger>
|
||||
<n-button type="error">
|
||||
<the-icon :size="16" icon="material-symbols:delete-outline" />
|
||||
{{ $gettext('Clear Monitoring Records') }}
|
||||
</n-button>
|
||||
</template>
|
||||
{{ $gettext('Are you sure you want to clear?') }}
|
||||
</n-popconfirm>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<n-grid
|
||||
v-if="!loading"
|
||||
cols="1 s:1 m:1 l:2 xl:2 2xl:2"
|
||||
|
||||
@@ -58,28 +58,31 @@ const handleCreate = () => {
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<common-page show-footer>
|
||||
<template #action>
|
||||
<n-button v-if="currentTab != 'user'" type="primary" @click="handleSave">
|
||||
<the-icon :size="18" icon="material-symbols:save-outline" />
|
||||
{{ $gettext('Save') }}
|
||||
</n-button>
|
||||
<n-button v-if="currentTab == 'user'" type="primary" @click="handleCreate">
|
||||
<the-icon :size="18" icon="material-symbols:add" />
|
||||
{{ $gettext('Create User') }}
|
||||
</n-button>
|
||||
<common-page show-header show-footer>
|
||||
<template #tabbar>
|
||||
<n-tabs v-model:value="currentTab" animated>
|
||||
<n-tab name="base" :tab="$gettext('Basic')" />
|
||||
<n-tab name="safe" :tab="$gettext('Safe')" />
|
||||
<n-tab name="user" :tab="$gettext('User')" />
|
||||
</n-tabs>
|
||||
</template>
|
||||
<n-tabs v-model:value="currentTab" type="line" animated>
|
||||
<n-tab-pane name="base" :tab="$gettext('Basic')">
|
||||
<setting-base v-model:model="model" />
|
||||
</n-tab-pane>
|
||||
<n-tab-pane name="safe" :tab="$gettext('Safe')">
|
||||
<setting-safe v-model:model="model" />
|
||||
</n-tab-pane>
|
||||
<n-tab-pane name="user" :tab="$gettext('User')">
|
||||
<setting-user />
|
||||
</n-tab-pane>
|
||||
</n-tabs>
|
||||
<n-flex vertical>
|
||||
<n-flex>
|
||||
<n-button v-if="currentTab == 'user'" type="primary" @click="handleCreate">
|
||||
<the-icon :size="18" icon="material-symbols:add" />
|
||||
{{ $gettext('Create User') }}
|
||||
</n-button>
|
||||
</n-flex>
|
||||
<setting-base v-if="currentTab === 'base'" v-model:model="model" />
|
||||
<setting-safe v-if="currentTab === 'safe'" v-model:model="model" />
|
||||
<setting-user v-if="currentTab === 'user'" />
|
||||
<n-flex>
|
||||
<n-button v-if="currentTab != 'user'" type="primary" @click="handleSave">
|
||||
<the-icon :size="18" icon="material-symbols:save-outline" />
|
||||
{{ $gettext('Save') }}
|
||||
</n-button>
|
||||
</n-flex>
|
||||
</n-flex>
|
||||
</common-page>
|
||||
<create-modal v-model:show="createModal" />
|
||||
</template>
|
||||
|
||||
@@ -225,12 +225,6 @@ onUnmounted(() => {
|
||||
|
||||
<template>
|
||||
<common-page show-footer>
|
||||
<template #action>
|
||||
<n-button type="primary" @click="create = true">
|
||||
<the-icon :size="18" icon="material-symbols:add" />
|
||||
{{ $gettext('Create Host') }}
|
||||
</n-button>
|
||||
</template>
|
||||
<n-layout has-sider sider-placement="right">
|
||||
<n-layout content-style="overflow: visible" bg-hex-111>
|
||||
<div ref="terminal" @wheel="onTermWheel" h-75vh></div>
|
||||
@@ -245,7 +239,14 @@ onUnmounted(() => {
|
||||
@expand="collapsed = false"
|
||||
@after-enter="onResize"
|
||||
@after-leave="onResize"
|
||||
pl-10
|
||||
>
|
||||
<div class="text-center">
|
||||
<n-button type="primary" @click="create = true">
|
||||
<the-icon :size="18" icon="material-symbols:add" />
|
||||
{{ $gettext('Create Host') }}
|
||||
</n-button>
|
||||
</div>
|
||||
<n-menu
|
||||
v-model:value="current"
|
||||
:collapsed="collapsed"
|
||||
|
||||
@@ -18,24 +18,25 @@ const create = ref(false)
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<common-page show-footer>
|
||||
<template #action>
|
||||
<n-button v-if="current == 'cron'" type="primary" @click="create = true">
|
||||
<the-icon :size="18" icon="material-symbols:add" />
|
||||
{{ $gettext('Create Task') }}
|
||||
</n-button>
|
||||
<common-page show-header show-footer>
|
||||
<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>
|
||||
<n-tabs v-model:value="current" type="line" animated>
|
||||
<n-tab-pane name="cron" :tab="$gettext('Scheduled Tasks')">
|
||||
<cron-view />
|
||||
</n-tab-pane>
|
||||
<n-tab-pane name="system" :tab="$gettext('System Processes')">
|
||||
<system-view />
|
||||
</n-tab-pane>
|
||||
<n-tab-pane name="task" :tab="$gettext('Panel Tasks')">
|
||||
<task-view />
|
||||
</n-tab-pane>
|
||||
</n-tabs>
|
||||
<n-flex vertical>
|
||||
<n-flex>
|
||||
<n-button v-if="current == 'cron'" type="primary" @click="create = true">
|
||||
<the-icon :size="18" icon="material-symbols:add" />
|
||||
{{ $gettext('Create Task') }}
|
||||
</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>
|
||||
<create-modal v-model:show="create" />
|
||||
</template>
|
||||
|
||||
@@ -83,195 +83,193 @@ const handleTest = async () => {
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<common-page show-footer>
|
||||
<n-flex vertical>
|
||||
<n-alert type="warning">
|
||||
{{
|
||||
$gettext(
|
||||
'Benchmark results are for reference only and may differ from actual performance due to system resource scheduling, caching, and other factors!'
|
||||
)
|
||||
}}
|
||||
</n-alert>
|
||||
<n-alert
|
||||
v-if="inTest"
|
||||
:title="$gettext('Benchmarking in progress, it may take some time...')"
|
||||
type="info"
|
||||
>
|
||||
{{ $gettext('Current project: %{ current }', { current: current }) }}
|
||||
</n-alert>
|
||||
<n-progress v-if="inTest" :percentage="progress" color="var(--primary-color)" processing />
|
||||
</n-flex>
|
||||
<n-flex vertical items-center pt-40>
|
||||
<div w-800>
|
||||
<n-grid :cols="3">
|
||||
<n-gi>
|
||||
<n-popover trigger="hover">
|
||||
<template #trigger>
|
||||
<n-flex vertical items-center>
|
||||
<div v-if="cpuTotal !== 0">
|
||||
<n-number-animation :from="0" :to="cpuTotal" show-separator />
|
||||
</div>
|
||||
<div v-else>{{ $gettext('Pending benchmark') }}</div>
|
||||
<n-progress
|
||||
type="circle"
|
||||
:percentage="100"
|
||||
:stroke-width="3"
|
||||
color="var(--primary-color)"
|
||||
>
|
||||
<the-icon :size="50" icon="bi:cpu" color="var(--primary-color)" />
|
||||
</n-progress>
|
||||
{{ $gettext('CPU') }}
|
||||
</n-flex>
|
||||
</template>
|
||||
<n-table :single-line="false" striped>
|
||||
<tr>
|
||||
<th>{{ $gettext('Image Processing') }}</th>
|
||||
<td>
|
||||
{{ cpu.image }}
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>{{ $gettext('Machine Learning') }}</th>
|
||||
<td>
|
||||
{{ cpu.machine }}
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>{{ $gettext('Program Compilation') }}</th>
|
||||
<td>
|
||||
{{ cpu.compile }}
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>{{ $gettext('AES Encryption') }}</th>
|
||||
<td>
|
||||
{{ cpu.encryption }}
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>{{ $gettext('Compression/Decompression') }}</th>
|
||||
<td>
|
||||
{{ cpu.compression }}
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>{{ $gettext('Physics Simulation') }}</th>
|
||||
<td>
|
||||
{{ cpu.physics }}
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>{{ $gettext('JSON Parsing') }}</th>
|
||||
<td>
|
||||
{{ cpu.json }}
|
||||
</td>
|
||||
</tr>
|
||||
</n-table>
|
||||
</n-popover>
|
||||
</n-gi>
|
||||
<n-gi>
|
||||
<n-popover trigger="hover">
|
||||
<template #trigger>
|
||||
<n-flex vertical items-center>
|
||||
<div v-if="memory.score !== 0">
|
||||
<n-number-animation :from="0" :to="memory.score" show-separator />
|
||||
</div>
|
||||
<div v-else>{{ $gettext('Pending benchmark') }}</div>
|
||||
<n-progress
|
||||
type="circle"
|
||||
:percentage="100"
|
||||
:stroke-width="3"
|
||||
color="var(--primary-color)"
|
||||
>
|
||||
<the-icon :size="50" icon="bi:memory" color="var(--primary-color)" />
|
||||
</n-progress>
|
||||
{{ $gettext('Memory') }}
|
||||
</n-flex>
|
||||
</template>
|
||||
<n-table :single-line="false" striped>
|
||||
<tr>
|
||||
<th>{{ $gettext('Memory Bandwidth') }}</th>
|
||||
<td>{{ memory.bandwidth }}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>{{ $gettext('Memory Latency') }}</th>
|
||||
<td>{{ memory.latency }}</td>
|
||||
</tr>
|
||||
</n-table>
|
||||
</n-popover>
|
||||
</n-gi>
|
||||
<n-gi>
|
||||
<n-popover trigger="hover">
|
||||
<template #trigger>
|
||||
<n-flex vertical items-center>
|
||||
<div v-if="disk.score !== 0">
|
||||
<n-number-animation :from="0" :to="disk.score" show-separator />
|
||||
</div>
|
||||
<div v-else>{{ $gettext('Pending benchmark') }}</div>
|
||||
<n-progress
|
||||
type="circle"
|
||||
:percentage="100"
|
||||
:stroke-width="3"
|
||||
color="var(--primary-color)"
|
||||
>
|
||||
<the-icon :size="50" icon="bi:hdd-stack" color="var(--primary-color)" />
|
||||
</n-progress>
|
||||
{{ $gettext('Disk') }}
|
||||
</n-flex>
|
||||
</template>
|
||||
<n-table :single-line="false" striped>
|
||||
<tr>
|
||||
<th>{{ $gettext('4KB Read') }}</th>
|
||||
<td>
|
||||
{{ disk['4'].read_speed }}
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>{{ $gettext('4KB Write') }}</th>
|
||||
<td>
|
||||
{{ disk['4'].write_speed }}
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>{{ $gettext('64KB Read') }}</th>
|
||||
<td>
|
||||
{{ disk['64'].read_speed }}
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>{{ $gettext('64KB Write') }}</th>
|
||||
<td>
|
||||
{{ disk['64'].write_speed }}
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>{{ $gettext('1MB Read') }}</th>
|
||||
<td>
|
||||
{{ disk['1024'].read_speed }}
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>{{ $gettext('1MB Write') }}</th>
|
||||
<td>
|
||||
{{ disk['1024'].write_speed }}
|
||||
</td>
|
||||
</tr>
|
||||
</n-table>
|
||||
</n-popover>
|
||||
</n-gi>
|
||||
</n-grid>
|
||||
</div>
|
||||
<n-button
|
||||
type="primary"
|
||||
size="large"
|
||||
:disabled="inTest"
|
||||
:loading="inTest"
|
||||
@click="handleTest"
|
||||
mt-40
|
||||
w-200
|
||||
>
|
||||
{{ inTest ? $gettext('Benchmarking...') : $gettext('Start Benchmark') }}
|
||||
</n-button>
|
||||
</n-flex>
|
||||
</common-page>
|
||||
<n-flex vertical>
|
||||
<n-alert type="warning">
|
||||
{{
|
||||
$gettext(
|
||||
'Benchmark results are for reference only and may differ from actual performance due to system resource scheduling, caching, and other factors!'
|
||||
)
|
||||
}}
|
||||
</n-alert>
|
||||
<n-alert
|
||||
v-if="inTest"
|
||||
:title="$gettext('Benchmarking in progress, it may take some time...')"
|
||||
type="info"
|
||||
>
|
||||
{{ $gettext('Current project: %{ current }', { current: current }) }}
|
||||
</n-alert>
|
||||
<n-progress v-if="inTest" :percentage="progress" color="var(--primary-color)" processing />
|
||||
</n-flex>
|
||||
<n-flex vertical items-center pt-40>
|
||||
<div w-800>
|
||||
<n-grid :cols="3">
|
||||
<n-gi>
|
||||
<n-popover trigger="hover">
|
||||
<template #trigger>
|
||||
<n-flex vertical items-center>
|
||||
<div v-if="cpuTotal !== 0">
|
||||
<n-number-animation :from="0" :to="cpuTotal" show-separator />
|
||||
</div>
|
||||
<div v-else>{{ $gettext('Pending benchmark') }}</div>
|
||||
<n-progress
|
||||
type="circle"
|
||||
:percentage="100"
|
||||
:stroke-width="3"
|
||||
color="var(--primary-color)"
|
||||
>
|
||||
<the-icon :size="50" icon="bi:cpu" color="var(--primary-color)" />
|
||||
</n-progress>
|
||||
{{ $gettext('CPU') }}
|
||||
</n-flex>
|
||||
</template>
|
||||
<n-table :single-line="false" striped>
|
||||
<tr>
|
||||
<th>{{ $gettext('Image Processing') }}</th>
|
||||
<td>
|
||||
{{ cpu.image }}
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>{{ $gettext('Machine Learning') }}</th>
|
||||
<td>
|
||||
{{ cpu.machine }}
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>{{ $gettext('Program Compilation') }}</th>
|
||||
<td>
|
||||
{{ cpu.compile }}
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>{{ $gettext('AES Encryption') }}</th>
|
||||
<td>
|
||||
{{ cpu.encryption }}
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>{{ $gettext('Compression/Decompression') }}</th>
|
||||
<td>
|
||||
{{ cpu.compression }}
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>{{ $gettext('Physics Simulation') }}</th>
|
||||
<td>
|
||||
{{ cpu.physics }}
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>{{ $gettext('JSON Parsing') }}</th>
|
||||
<td>
|
||||
{{ cpu.json }}
|
||||
</td>
|
||||
</tr>
|
||||
</n-table>
|
||||
</n-popover>
|
||||
</n-gi>
|
||||
<n-gi>
|
||||
<n-popover trigger="hover">
|
||||
<template #trigger>
|
||||
<n-flex vertical items-center>
|
||||
<div v-if="memory.score !== 0">
|
||||
<n-number-animation :from="0" :to="memory.score" show-separator />
|
||||
</div>
|
||||
<div v-else>{{ $gettext('Pending benchmark') }}</div>
|
||||
<n-progress
|
||||
type="circle"
|
||||
:percentage="100"
|
||||
:stroke-width="3"
|
||||
color="var(--primary-color)"
|
||||
>
|
||||
<the-icon :size="50" icon="bi:memory" color="var(--primary-color)" />
|
||||
</n-progress>
|
||||
{{ $gettext('Memory') }}
|
||||
</n-flex>
|
||||
</template>
|
||||
<n-table :single-line="false" striped>
|
||||
<tr>
|
||||
<th>{{ $gettext('Memory Bandwidth') }}</th>
|
||||
<td>{{ memory.bandwidth }}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>{{ $gettext('Memory Latency') }}</th>
|
||||
<td>{{ memory.latency }}</td>
|
||||
</tr>
|
||||
</n-table>
|
||||
</n-popover>
|
||||
</n-gi>
|
||||
<n-gi>
|
||||
<n-popover trigger="hover">
|
||||
<template #trigger>
|
||||
<n-flex vertical items-center>
|
||||
<div v-if="disk.score !== 0">
|
||||
<n-number-animation :from="0" :to="disk.score" show-separator />
|
||||
</div>
|
||||
<div v-else>{{ $gettext('Pending benchmark') }}</div>
|
||||
<n-progress
|
||||
type="circle"
|
||||
:percentage="100"
|
||||
:stroke-width="3"
|
||||
color="var(--primary-color)"
|
||||
>
|
||||
<the-icon :size="50" icon="bi:hdd-stack" color="var(--primary-color)" />
|
||||
</n-progress>
|
||||
{{ $gettext('Disk') }}
|
||||
</n-flex>
|
||||
</template>
|
||||
<n-table :single-line="false" striped>
|
||||
<tr>
|
||||
<th>{{ $gettext('4KB Read') }}</th>
|
||||
<td>
|
||||
{{ disk['4'].read_speed }}
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>{{ $gettext('4KB Write') }}</th>
|
||||
<td>
|
||||
{{ disk['4'].write_speed }}
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>{{ $gettext('64KB Read') }}</th>
|
||||
<td>
|
||||
{{ disk['64'].read_speed }}
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>{{ $gettext('64KB Write') }}</th>
|
||||
<td>
|
||||
{{ disk['64'].write_speed }}
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>{{ $gettext('1MB Read') }}</th>
|
||||
<td>
|
||||
{{ disk['1024'].read_speed }}
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>{{ $gettext('1MB Write') }}</th>
|
||||
<td>
|
||||
{{ disk['1024'].write_speed }}
|
||||
</td>
|
||||
</tr>
|
||||
</n-table>
|
||||
</n-popover>
|
||||
</n-gi>
|
||||
</n-grid>
|
||||
</div>
|
||||
<n-button
|
||||
type="primary"
|
||||
size="large"
|
||||
:disabled="inTest"
|
||||
:loading="inTest"
|
||||
@click="handleTest"
|
||||
mt-40
|
||||
w-200
|
||||
>
|
||||
{{ inTest ? $gettext('Benchmarking...') : $gettext('Start Benchmark') }}
|
||||
</n-button>
|
||||
</n-flex>
|
||||
</template>
|
||||
|
||||
29
web/src/views/toolbox/IndexView.vue
Normal file
29
web/src/views/toolbox/IndexView.vue
Normal file
@@ -0,0 +1,29 @@
|
||||
<script setup lang="ts">
|
||||
defineOptions({
|
||||
name: 'toolbox-index'
|
||||
})
|
||||
|
||||
import BenchmarkView from '@/views/toolbox/BenchmarkView.vue'
|
||||
import SystemView from '@/views/toolbox/SystemView.vue'
|
||||
import { useGettext } from 'vue3-gettext'
|
||||
|
||||
const { $gettext } = useGettext()
|
||||
const current = ref('system')
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<common-page show-header show-footer>
|
||||
<template #tabbar>
|
||||
<n-tabs v-model:value="current" animated>
|
||||
<n-tab name="system" :tab="$gettext('System')" />
|
||||
<n-tab name="benchmark" :tab="$gettext('Benchmark')" />
|
||||
</n-tabs>
|
||||
</template>
|
||||
<n-flex vertical>
|
||||
<system-view v-if="current === 'system'" />
|
||||
<benchmark-view v-if="current === 'benchmark'" />
|
||||
</n-flex>
|
||||
</common-page>
|
||||
</template>
|
||||
|
||||
<style scoped lang="scss"></style>
|
||||
@@ -5,7 +5,6 @@ defineOptions({
|
||||
|
||||
import Editor from '@guolao/vue-monaco-editor'
|
||||
import { DateTime } from 'luxon'
|
||||
import { NButton } from 'naive-ui'
|
||||
import { useGettext } from 'vue3-gettext'
|
||||
|
||||
import system from '@/api/panel/toolbox-system'
|
||||
@@ -90,76 +89,57 @@ const handleSyncTime = () => {
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<common-page show-footer>
|
||||
<template #action>
|
||||
<n-button v-if="currentTab == 'dns'" class="ml-16" type="primary" @click="handleUpdateDNS">
|
||||
<the-icon :size="18" icon="material-symbols:save-outline" />
|
||||
{{ $gettext('Save') }}
|
||||
</n-button>
|
||||
<n-button v-if="currentTab == 'swap'" class="ml-16" type="primary" @click="handleUpdateSwap">
|
||||
<the-icon :size="18" icon="material-symbols:save-outline" />
|
||||
{{ $gettext('Save') }}
|
||||
</n-button>
|
||||
<n-button v-if="currentTab == 'host'" class="ml-16" type="primary" @click="handleUpdateHost">
|
||||
<the-icon :size="18" icon="material-symbols:save-outline" />
|
||||
{{ $gettext('Save') }}
|
||||
</n-button>
|
||||
<n-button v-if="currentTab == 'time'" class="ml-16" type="primary" @click="handleUpdateTime">
|
||||
<the-icon :size="18" icon="material-symbols:save-outline" />
|
||||
{{ $gettext('Save') }}
|
||||
</n-button>
|
||||
<n-button
|
||||
v-if="currentTab == 'root-password'"
|
||||
class="ml-16"
|
||||
type="primary"
|
||||
@click="handleUpdateRootPassword"
|
||||
>
|
||||
<the-icon :size="18" icon="material-symbols:save-outline" />
|
||||
{{ $gettext('Modify') }}
|
||||
</n-button>
|
||||
</template>
|
||||
<n-tabs v-model:value="currentTab" type="line" animated>
|
||||
<n-tab-pane name="dns" tab="DNS">
|
||||
<n-flex vertical>
|
||||
<n-alert type="warning">
|
||||
{{ $gettext('DNS modifications will revert to default after system restart.') }}
|
||||
</n-alert>
|
||||
<n-form>
|
||||
<n-form-item label="DNS1">
|
||||
<n-input v-model:value="dns1" />
|
||||
</n-form-item>
|
||||
<n-form-item label="DNS2">
|
||||
<n-input v-model:value="dns2" />
|
||||
</n-form-item>
|
||||
</n-form>
|
||||
<n-tabs v-model:value="currentTab" type="line" placement="left" animated>
|
||||
<n-tab-pane name="dns" tab="DNS">
|
||||
<n-flex vertical>
|
||||
<n-alert type="warning">
|
||||
{{ $gettext('DNS modifications will revert to default after system restart.') }}
|
||||
</n-alert>
|
||||
<n-form>
|
||||
<n-form-item label="DNS1">
|
||||
<n-input v-model:value="dns1" />
|
||||
</n-form-item>
|
||||
<n-form-item label="DNS2">
|
||||
<n-input v-model:value="dns2" />
|
||||
</n-form-item>
|
||||
</n-form>
|
||||
<n-flex>
|
||||
<n-button type="primary" @click="handleUpdateDNS">
|
||||
{{ $gettext('Save') }}
|
||||
</n-button>
|
||||
</n-flex>
|
||||
</n-tab-pane>
|
||||
<n-tab-pane name="swap" tab="SWAP">
|
||||
<n-flex vertical>
|
||||
<n-alert type="info">
|
||||
{{
|
||||
$gettext('Total %{ total }, used %{ used }, free %{ free }', {
|
||||
total: swapTotal,
|
||||
used: swapUsed,
|
||||
free: swapFree
|
||||
})
|
||||
}}
|
||||
</n-alert>
|
||||
<n-form>
|
||||
<n-form-item :label="$gettext('SWAP Size')">
|
||||
<n-input-number v-model:value="swap" />
|
||||
MB
|
||||
</n-form-item>
|
||||
</n-form>
|
||||
</n-flex>
|
||||
</n-tab-pane>
|
||||
<n-tab-pane name="swap" tab="SWAP">
|
||||
<n-flex vertical>
|
||||
<n-alert type="info">
|
||||
{{
|
||||
$gettext('Total %{ total }, used %{ used }, free %{ free }', {
|
||||
total: swapTotal,
|
||||
used: swapUsed,
|
||||
free: swapFree
|
||||
})
|
||||
}}
|
||||
</n-alert>
|
||||
<n-form>
|
||||
<n-form-item :label="$gettext('SWAP Size')">
|
||||
<n-input-number v-model:value="swap" />
|
||||
MB
|
||||
</n-form-item>
|
||||
</n-form>
|
||||
<n-flex>
|
||||
<n-button type="primary" @click="handleUpdateSwap">
|
||||
{{ $gettext('Save') }}
|
||||
</n-button>
|
||||
</n-flex>
|
||||
</n-tab-pane>
|
||||
<n-tab-pane name="host" :tab="$gettext('Host')">
|
||||
<n-flex vertical>
|
||||
<n-form>
|
||||
<n-form-item :label="$gettext('Hostname')">
|
||||
<n-input v-model:value="hostname" />
|
||||
</n-form-item>
|
||||
</n-form>
|
||||
</n-flex>
|
||||
</n-tab-pane>
|
||||
<n-tab-pane name="host" :tab="$gettext('Host')">
|
||||
<n-form>
|
||||
<n-form-item :label="$gettext('Hostname')">
|
||||
<n-input v-model:value="hostname" />
|
||||
</n-form-item>
|
||||
<n-form-item :label="$gettext('Hosts')">
|
||||
<Editor
|
||||
v-model:value="hosts"
|
||||
language="ini"
|
||||
@@ -172,43 +152,52 @@ const handleSyncTime = () => {
|
||||
formatOnPaste: true
|
||||
}"
|
||||
/>
|
||||
</n-flex>
|
||||
</n-tab-pane>
|
||||
<n-tab-pane name="time" :tab="$gettext('Time')">
|
||||
<n-flex vertical>
|
||||
<n-alert type="info">
|
||||
{{
|
||||
$gettext(
|
||||
'After manually changing the time, it may still be overwritten by system automatic time synchronization.'
|
||||
)
|
||||
}}
|
||||
</n-alert>
|
||||
<n-form>
|
||||
<n-form-item :label="$gettext('Select Timezone')">
|
||||
<n-select
|
||||
v-model:value="timezone"
|
||||
:placeholder="$gettext('Please select a timezone')"
|
||||
:options="timezones"
|
||||
/>
|
||||
</n-form-item>
|
||||
<n-form-item :label="$gettext('Modify Time')">
|
||||
<n-date-picker v-model:value="time" type="datetime" clearable />
|
||||
</n-form-item>
|
||||
<n-form-item :label="$gettext('NTP Time Synchronization')">
|
||||
<n-button type="info" @click="handleSyncTime">{{
|
||||
$gettext('Synchronize Time')
|
||||
}}</n-button>
|
||||
</n-form-item>
|
||||
</n-form>
|
||||
</n-flex>
|
||||
</n-tab-pane>
|
||||
<n-tab-pane name="root-password" :tab="$gettext('Root Password')">
|
||||
</n-form-item>
|
||||
</n-form>
|
||||
<n-button type="primary" @click="handleUpdateHost">
|
||||
{{ $gettext('Save') }}
|
||||
</n-button>
|
||||
</n-tab-pane>
|
||||
<n-tab-pane name="time" :tab="$gettext('Time')">
|
||||
<n-flex vertical>
|
||||
<n-alert type="info">
|
||||
{{
|
||||
$gettext(
|
||||
'After manually changing the time, it may still be overwritten by system automatic time synchronization.'
|
||||
)
|
||||
}}
|
||||
</n-alert>
|
||||
<n-form>
|
||||
<n-form-item :label="$gettext('Root Password')">
|
||||
<n-input v-model:value="rootPassword" type="password" show-password-on="click" />
|
||||
<n-form-item :label="$gettext('Select Timezone')">
|
||||
<n-select
|
||||
v-model:value="timezone"
|
||||
:placeholder="$gettext('Please select a timezone')"
|
||||
:options="timezones"
|
||||
/>
|
||||
</n-form-item>
|
||||
<n-form-item :label="$gettext('Modify Time')">
|
||||
<n-date-picker v-model:value="time" type="datetime" clearable />
|
||||
</n-form-item>
|
||||
</n-form>
|
||||
</n-tab-pane>
|
||||
</n-tabs>
|
||||
</common-page>
|
||||
<n-flex>
|
||||
<n-button type="primary" @click="handleUpdateTime">
|
||||
{{ $gettext('Save') }}
|
||||
</n-button>
|
||||
<n-button type="info" @click="handleSyncTime">
|
||||
{{ $gettext('Synchronize Time') }}
|
||||
</n-button>
|
||||
</n-flex>
|
||||
</n-flex>
|
||||
</n-tab-pane>
|
||||
<n-tab-pane name="root-password" :tab="$gettext('Root Password')">
|
||||
<n-form>
|
||||
<n-form-item :label="$gettext('Root Password')">
|
||||
<n-input v-model:value="rootPassword" type="password" show-password-on="click" />
|
||||
</n-form-item>
|
||||
</n-form>
|
||||
<n-button type="primary" @click="handleUpdateRootPassword">
|
||||
{{ $gettext('Save') }}
|
||||
</n-button>
|
||||
</n-tab-pane>
|
||||
</n-tabs>
|
||||
</template>
|
||||
|
||||
@@ -7,27 +7,16 @@ export default {
|
||||
path: '/toolbox',
|
||||
component: Layout,
|
||||
meta: {
|
||||
title: 'Toolbox',
|
||||
icon: 'mdi:tools',
|
||||
order: 90
|
||||
},
|
||||
children: [
|
||||
{
|
||||
name: 'toolbox-system',
|
||||
path: 'system',
|
||||
component: () => import('./SystemView.vue'),
|
||||
name: 'toolbox-index',
|
||||
path: '',
|
||||
component: () => import('./IndexView.vue'),
|
||||
meta: {
|
||||
title: 'System',
|
||||
role: ['admin'],
|
||||
requireAuth: true
|
||||
}
|
||||
},
|
||||
{
|
||||
name: 'toolbox-benchmark',
|
||||
path: 'benchmark',
|
||||
component: () => import('./BenchmarkView.vue'),
|
||||
meta: {
|
||||
title: 'Benchmark',
|
||||
title: 'Toolbox',
|
||||
icon: 'mdi:tools',
|
||||
role: ['admin'],
|
||||
requireAuth: true
|
||||
}
|
||||
|
||||
@@ -376,8 +376,16 @@ onMounted(() => {
|
||||
|
||||
<template>
|
||||
<common-page show-footer>
|
||||
<template #action>
|
||||
<n-flex vertical>
|
||||
<n-flex>
|
||||
<n-button type="primary" @click="createModal = true">
|
||||
<the-icon :size="18" icon="material-symbols:add" />
|
||||
{{ $gettext('Create Website') }}
|
||||
</n-button>
|
||||
<n-button type="primary" @click="bulkCreateModal = true">
|
||||
<the-icon :size="18" icon="material-symbols:add" />
|
||||
{{ $gettext('Bulk Create Website') }}
|
||||
</n-button>
|
||||
<n-button type="warning" @click="editDefaultPageModal = true">
|
||||
<the-icon :size="18" icon="material-symbols:edit-document-outline" />
|
||||
{{ $gettext('Modify Default Page') }}
|
||||
@@ -395,17 +403,7 @@ onMounted(() => {
|
||||
)
|
||||
}}
|
||||
</n-popconfirm>
|
||||
<n-button type="primary" @click="bulkCreateModal = true">
|
||||
<the-icon :size="18" icon="material-symbols:add" />
|
||||
{{ $gettext('Bulk Create Website') }}
|
||||
</n-button>
|
||||
<n-button type="primary" @click="createModal = true">
|
||||
<the-icon :size="18" icon="material-symbols:add" />
|
||||
{{ $gettext('Create Website') }}
|
||||
</n-button>
|
||||
</n-flex>
|
||||
</template>
|
||||
<n-flex vertical :size="20">
|
||||
<n-data-table
|
||||
striped
|
||||
remote
|
||||
|
||||
Reference in New Issue
Block a user