2
0
mirror of https://github.com/acepanel/panel.git synced 2026-02-04 09:13:49 +08:00

feat: 前端样式优化

This commit is contained in:
耗子
2025-02-09 22:06:07 +08:00
parent 9648b24d58
commit 8c8a957df1
21 changed files with 268 additions and 271 deletions

View File

@@ -186,7 +186,13 @@ func (r *websiteRepo) Get(id uint) (*types.WebsiteSetting, error) {
rewrite, _ := io.Read(filepath.Join(app.Root, "server/vhost/rewrite", website.Name+".conf"))
setting.Rewrite = rewrite
// 访问日志
setting.Log = fmt.Sprintf("%s/wwwlogs/%s.log", app.Root, website.Name)
if setting.Log, err = p.GetAccessLog(); err != nil {
setting.Log = fmt.Sprintf("%s/wwwlogs/%s.log", app.Root, website.Name)
}
// 错误日志
if setting.ErrorLog, err = p.GetErrorLog(); err != nil {
setting.ErrorLog = fmt.Sprintf("%s/wwwlogs/%s.error.log", app.Root, website.Name)
}
return setting, err
}

View File

@@ -32,4 +32,5 @@ type WebsiteSetting struct {
Rewrite string `json:"rewrite"`
Raw string `json:"raw"`
Log string `json:"log"`
ErrorLog string `json:"error_log"`
}

View File

@@ -27,7 +27,6 @@ export const http = createAlova({
const { meta } = method
if (status !== 200) {
const code = json?.code ?? status
console.log(json)
const message = resolveResError(
code,
(typeof json?.message === 'string' && json.message.trim()) || statusText

View File

@@ -468,6 +468,7 @@ onUnmounted(() => {
v-model:value="updateModel.cert"
type="textarea"
placeholder="输入 PEM 证书文件的内容"
:autosize="{ minRows: 10, maxRows: 15 }"
/>
</n-form-item>
<n-form-item v-if="updateModel.type == 'upload'" path="key" label="私钥">
@@ -475,6 +476,7 @@ onUnmounted(() => {
v-model:value="updateModel.key"
type="textarea"
placeholder="输入 KEY 私钥文件的内容"
:autosize="{ minRows: 10, maxRows: 15 }"
/>
</n-form-item>
</n-form>

View File

@@ -38,6 +38,7 @@ const handleSubmit = () => {
v-model:value="model.cert"
type="textarea"
placeholder="输入 PEM 证书文件的内容"
:autosize="{ minRows: 10, maxRows: 15 }"
/>
</n-form-item>
<n-form-item label="私钥">
@@ -45,6 +46,7 @@ const handleSubmit = () => {
v-model:value="model.key"
type="textarea"
placeholder="输入 KEY 私钥文件的内容"
:autosize="{ minRows: 10, maxRows: 15 }"
/>
</n-form-item>
</n-form>

View File

@@ -429,46 +429,42 @@ onMounted(() => {
</script>
<template>
<n-space vertical size="large">
<n-card rounded-10>
<n-space>
<n-button type="primary" @click="containerCreateModal = true">创建容器</n-button>
<n-button type="primary" @click="handlePrune" ghost>清理容器</n-button>
<n-button-group>
<n-button @click="bulkStart">启动</n-button>
<n-button @click="bulkStop">停止</n-button>
<n-button @click="bulkRestart">重启</n-button>
<n-button @click="bulkForceStop">强制停止</n-button>
<n-button @click="bulkPause">暂停</n-button>
<n-button @click="bulkUnpause">恢复</n-button>
<n-button @click="bulkDelete">删除</n-button>
</n-button-group>
</n-space>
</n-card>
<n-card rounded-10>
<n-data-table
striped
remote
:loading="loading"
:scroll-x="1000"
:data="data"
:columns="columns"
:row-key="(row: any) => row.id"
v-model:checked-row-keys="selectedRowKeys"
v-model:page="page"
v-model:pageSize="pageSize"
:pagination="{
page: page,
pageCount: pageCount,
pageSize: pageSize,
itemCount: total,
showQuickJumper: true,
showSizePicker: true,
pageSizes: [20, 50, 100, 200]
}"
/>
</n-card>
</n-space>
<n-flex vertical :size="20">
<n-flex>
<n-button type="primary" @click="containerCreateModal = true">创建容器</n-button>
<n-button type="primary" @click="handlePrune" ghost>清理容器</n-button>
<n-button-group>
<n-button @click="bulkStart">启动</n-button>
<n-button @click="bulkStop">停止</n-button>
<n-button @click="bulkRestart">重启</n-button>
<n-button @click="bulkForceStop">强制停止</n-button>
<n-button @click="bulkPause">暂停</n-button>
<n-button @click="bulkUnpause">恢复</n-button>
<n-button @click="bulkDelete">删除</n-button>
</n-button-group>
</n-flex>
<n-data-table
striped
remote
:loading="loading"
:scroll-x="1000"
:data="data"
:columns="columns"
:row-key="(row: any) => row.id"
v-model:checked-row-keys="selectedRowKeys"
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>
<n-modal
v-model:show="logModal"
preset="card"

View File

@@ -143,37 +143,33 @@ onMounted(() => {
</script>
<template>
<n-space vertical size="large">
<n-card rounded-10>
<n-space>
<n-button type="primary" @click="pullModal = true">拉取镜像</n-button>
<n-button type="primary" @click="handlePrune" ghost>清理镜像</n-button>
</n-space>
</n-card>
<n-card rounded-10>
<n-data-table
striped
remote
:loading="loading"
:scroll-x="1000"
:data="data"
:columns="columns"
:row-key="(row: any) => row.id"
v-model:checked-row-keys="selectedRowKeys"
v-model:page="page"
v-model:pageSize="pageSize"
:pagination="{
page: page,
pageCount: pageCount,
pageSize: pageSize,
itemCount: total,
showQuickJumper: true,
showSizePicker: true,
pageSizes: [20, 50, 100, 200]
}"
/>
</n-card>
</n-space>
<n-flex vertical :size="20">
<n-flex>
<n-button type="primary" @click="pullModal = true">拉取镜像</n-button>
<n-button type="primary" @click="handlePrune" ghost>清理镜像</n-button>
</n-flex>
<n-data-table
striped
remote
:loading="loading"
:scroll-x="1000"
:data="data"
:columns="columns"
:row-key="(row: any) => row.id"
v-model:checked-row-keys="selectedRowKeys"
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>
<n-modal
v-model:show="pullModal"
preset="card"

View File

@@ -13,7 +13,7 @@ const current = ref('container')
<template>
<common-page show-footer>
<n-tabs v-model:value="current" type="line" animated size="large">
<n-tabs v-model:value="current" type="line" animated>
<n-tab-pane name="container" tab="容器">
<container-view />
</n-tab-pane>

View File

@@ -182,37 +182,33 @@ onMounted(() => {
</script>
<template>
<n-space vertical size="large">
<n-card rounded-10>
<n-space>
<n-button type="primary" @click="createModal = true">创建网络</n-button>
<n-button type="primary" @click="handlePrune" ghost>清理网络</n-button>
</n-space>
</n-card>
<n-card rounded-10>
<n-data-table
striped
remote
:loading="loading"
:scroll-x="1000"
:data="data"
:columns="columns"
:row-key="(row: any) => row.id"
v-model:checked-row-keys="selectedRowKeys"
v-model:page="page"
v-model:pageSize="pageSize"
:pagination="{
page: page,
pageCount: pageCount,
pageSize: pageSize,
itemCount: total,
showQuickJumper: true,
showSizePicker: true,
pageSizes: [20, 50, 100, 200]
}"
/>
</n-card>
</n-space>
<n-flex vertical :size="20">
<n-flex>
<n-button type="primary" @click="createModal = true">创建网络</n-button>
<n-button type="primary" @click="handlePrune" ghost>清理网络</n-button>
</n-flex>
<n-data-table
striped
remote
:loading="loading"
:scroll-x="1000"
:data="data"
:columns="columns"
:row-key="(row: any) => row.id"
v-model:checked-row-keys="selectedRowKeys"
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>
<n-modal
v-model:show="createModal"
preset="card"

View File

@@ -137,37 +137,33 @@ onMounted(() => {
</script>
<template>
<n-space vertical size="large">
<n-card rounded-10>
<n-space>
<n-button type="primary" @click="createModal = true">创建</n-button>
<n-button type="primary" @click="handlePrune" ghost>清理卷</n-button>
</n-space>
</n-card>
<n-card rounded-10>
<n-data-table
striped
remote
:loading="loading"
:scroll-x="1000"
:data="data"
:columns="columns"
:row-key="(row: any) => row.id"
v-model:checked-row-keys="selectedRowKeys"
v-model:page="page"
v-model:pageSize="pageSize"
:pagination="{
page: page,
pageCount: pageCount,
pageSize: pageSize,
itemCount: total,
showQuickJumper: true,
showSizePicker: true,
pageSizes: [20, 50, 100, 200]
}"
/>
</n-card>
</n-space>
<n-flex vertical :size="20">
<n-flex>
<n-button type="primary" @click="createModal = true">创建卷</n-button>
<n-button type="primary" @click="handlePrune" ghost>清理</n-button>
</n-flex>
<n-data-table
striped
remote
:loading="loading"
:scroll-x="1000"
:data="data"
:columns="columns"
:row-key="(row: any) => row.id"
v-model:checked-row-keys="selectedRowKeys"
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>
<n-modal
v-model:show="createModal"
preset="card"

View File

@@ -160,24 +160,22 @@ onMounted(() => {
</script>
<template>
<n-flex vertical>
<n-card flex-1 rounded-10>
<n-flex items-center>
<n-button type="primary" @click="createModalShow = true">
<TheIcon :size="18" icon="material-symbols:add" />
创建转发
</n-button>
<n-popconfirm @positive-click="batchDelete">
<template #trigger>
<n-button type="warning">
<TheIcon :size="18" icon="material-symbols:delete-outline" />
批量删除
</n-button>
</template>
确定要批量删除吗
</n-popconfirm>
</n-flex>
</n-card>
<n-flex vertical :size="20">
<n-flex items-center>
<n-button type="primary" @click="createModalShow = true">
<TheIcon :size="18" icon="material-symbols:add" />
创建转发
</n-button>
<n-popconfirm @positive-click="batchDelete">
<template #trigger>
<n-button type="warning">
<TheIcon :size="18" icon="material-symbols:delete-outline" />
批量删除
</n-button>
</template>
确定要批量删除吗
</n-popconfirm>
</n-flex>
<n-data-table
striped
remote

View File

@@ -13,7 +13,7 @@ const currentTab = ref('rule')
<template>
<common-page show-footer>
<n-tabs v-model:value="currentTab" type="line" animated size="large">
<n-tabs v-model:value="currentTab" type="line" animated>
<n-tab-pane name="rule" tab="端口规则">
<rule-view />
</n-tab-pane>

View File

@@ -202,24 +202,22 @@ onMounted(() => {
</script>
<template>
<n-flex vertical>
<n-card flex-1 rounded-10>
<n-flex items-center>
<n-button type="primary" @click="createModalShow = true">
<TheIcon :size="18" icon="material-symbols:add" />
创建规则
</n-button>
<n-popconfirm @positive-click="batchDelete">
<template #trigger>
<n-button type="warning">
<TheIcon :size="18" icon="material-symbols:delete-outline" />
批量删除
</n-button>
</template>
确定要批量删除吗
</n-popconfirm>
</n-flex>
</n-card>
<n-flex vertical :size="20">
<n-flex items-center>
<n-button type="primary" @click="createModalShow = true">
<TheIcon :size="18" icon="material-symbols:add" />
创建规则
</n-button>
<n-popconfirm @positive-click="batchDelete">
<template #trigger>
<n-button type="warning">
<TheIcon :size="18" icon="material-symbols:delete-outline" />
批量删除
</n-button>
</template>
确定要批量删除吗
</n-popconfirm>
</n-flex>
<n-data-table
striped
remote

View File

@@ -241,24 +241,22 @@ onMounted(() => {
</script>
<template>
<n-flex vertical>
<n-card flex-1 rounded-10>
<n-flex items-center>
<n-button type="primary" @click="createModalShow = true">
<TheIcon :size="18" icon="material-symbols:add" />
创建规则
</n-button>
<n-popconfirm @positive-click="batchDelete">
<template #trigger>
<n-button type="warning">
<TheIcon :size="18" icon="material-symbols:delete-outline" />
批量删除
</n-button>
</template>
确定要批量删除吗
</n-popconfirm>
</n-flex>
</n-card>
<n-flex vertical :size="20">
<n-flex items-center>
<n-button type="primary" @click="createModalShow = true">
<TheIcon :size="18" icon="material-symbols:add" />
创建规则
</n-button>
<n-popconfirm @positive-click="batchDelete">
<template #trigger>
<n-button type="warning">
<TheIcon :size="18" icon="material-symbols:delete-outline" />
批量删除
</n-button>
</template>
确定要批量删除吗
</n-popconfirm>
</n-flex>
<n-data-table
striped
remote

View File

@@ -40,22 +40,20 @@ const handlePingStatus = () => {
</script>
<template>
<n-card flex-1 rounded-10>
<n-form :model="model" label-placement="left" label-width="auto">
<n-form-item path="firewall" label="系统防火墙">
<n-switch v-model:value="model.firewallStatus" @update:value="handleFirewallStatus" />
</n-form-item>
<n-form-item path="ssh" label="SSH 开关">
<n-switch v-model:value="model.sshStatus" @update:value="handleSsh" />
</n-form-item>
<n-form-item path="ping" label="允许 Ping">
<n-switch v-model:value="model.pingStatus" @update:value="handlePingStatus" />
</n-form-item>
<n-form-item path="sshPort" label="SSH 端口">
<n-input-number v-model:value="model.sshPort" @blur="handleSsh" />
</n-form-item>
</n-form>
</n-card>
<n-form :model="model" label-placement="left" label-width="auto">
<n-form-item path="firewall" label="系统防火墙">
<n-switch v-model:value="model.firewallStatus" @update:value="handleFirewallStatus" />
</n-form-item>
<n-form-item path="ssh" label="SSH 开关">
<n-switch v-model:value="model.sshStatus" @update:value="handleSsh" />
</n-form-item>
<n-form-item path="ping" label="允许 Ping">
<n-switch v-model:value="model.pingStatus" @update:value="handlePingStatus" />
</n-form-item>
<n-form-item path="sshPort" label="SSH 端口">
<n-input-number v-model:value="model.sshPort" @blur="handleSsh" />
</n-form-item>
</n-form>
</template>
<style scoped lang="scss"></style>

View File

@@ -481,22 +481,22 @@ watch(data, () => {
pt-20
>
<n-gi m-10>
<n-card :segmented="true" rounded-10 style="height: 40vh">
<n-card :bordered="false" style="height: 40vh">
<v-chart class="chart" :option="load" autoresize />
</n-card>
</n-gi>
<n-gi m-10>
<n-card :segmented="true" rounded-10 style="height: 40vh">
<n-card :bordered="false" style="height: 40vh">
<v-chart class="chart" :option="cpu" autoresize />
</n-card>
</n-gi>
<n-gi m-10>
<n-card :segmented="true" rounded-10 style="height: 40vh">
<n-card :bordered="false" style="height: 40vh">
<v-chart class="chart" :option="mem" autoresize />
</n-card>
</n-gi>
<n-gi m-10>
<n-card :segmented="true" rounded-10 style="height: 40vh">
<n-card :bordered="false" style="height: 40vh">
<v-chart class="chart" :option="net" autoresize />
</n-card>
</n-gi>

View File

@@ -32,16 +32,24 @@ const handleSave = () => {
<template>
<n-space vertical>
<n-alert type="warning"> 错误的证书导致面板无法访问请谨慎操作</n-alert>
<n-alert type="warning"> 错误的证书可能导致面板无法访问请谨慎操作</n-alert>
<n-form>
<n-form-item :label="$t('settingIndex.edit.fields.https.label')">
<n-switch v-model:value="model.https" />
</n-form-item>
<n-form-item v-if="model.https" :label="$t('settingIndex.edit.fields.cert.label')">
<n-input v-model:value="model.cert" type="textarea" />
<n-input
v-model:value="model.cert"
type="textarea"
:autosize="{ minRows: 10, maxRows: 15 }"
/>
</n-form-item>
<n-form-item v-if="model.https" :label="$t('settingIndex.edit.fields.key.label')">
<n-input v-model:value="model.key" type="textarea" />
<n-input
v-model:value="model.key"
type="textarea"
:autosize="{ minRows: 10, maxRows: 15 }"
/>
</n-form-item>
</n-form>
</n-space>

View File

@@ -222,28 +222,26 @@ onUnmounted(() => {
</script>
<template>
<n-card flex-1 rounded-10>
<n-data-table
striped
remote
:scroll-x="1300"
:loading="loading"
:columns="columns"
:data="data"
:row-key="(row: any) => row.id"
v-model:page="page"
v-model:pageSize="pageSize"
:pagination="{
page: page,
pageCount: pageCount,
pageSize: pageSize,
itemCount: total,
showQuickJumper: true,
showSizePicker: true,
pageSizes: [20, 50, 100, 200]
}"
/>
</n-card>
<n-data-table
striped
remote
:scroll-x="1300"
:loading="loading"
:columns="columns"
:data="data"
:row-key="(row: any) => row.id"
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]
}"
/>
<realtime-log-modal v-model:show="logModal" :path="logPath" />
<n-modal
v-model:show="editModal"

View File

@@ -23,7 +23,7 @@ const create = ref(false)
创建任务
</n-button>
</template>
<n-tabs v-model:value="current" type="line" animated size="large">
<n-tabs v-model:value="current" type="line" animated>
<n-tab-pane name="cron" tab="计划任务">
<cron-view />
</n-tab-pane>

View File

@@ -40,7 +40,8 @@ const { data: setting, send: fetchSetting } = useRequest(website.config(Number(i
ocsp: false,
rewrite: '',
raw: '',
log: ''
log: '',
error_log: ''
}
})
const { data: installedDbAndPhp } = useRequest(dashboard.installedDbAndPhp, {
@@ -77,7 +78,7 @@ const title = computed(() => {
if (setting.value) {
return `编辑网站 - ${setting.value.name}`
}
return '编辑网站 - 加载中...'
return '编辑网站'
})
const certOptions = computed(() => {
return certs.value.map((item: any) => ({
@@ -141,9 +142,11 @@ const handleObtainCert = () => {
const handleSelectCert = (value: number) => {
const cert = certs.value.find((item: any) => item.id === value)
if (cert) {
if (cert && cert.cert !== '' && cert.key !== '') {
setting.value.ssl_certificate = cert.cert
setting.value.ssl_certificate_key = cert.key
} else {
window.$message.error('选择的证书无效')
}
}
@@ -299,7 +302,7 @@ const onCreateListen = () => {
</n-card>
<n-form>
<n-grid :cols="24" :x-gap="24">
<n-form-item-gi :span="12" label="总开关(只有打开了总开关,下面的设置才会生效!)">
<n-form-item-gi :span="12" label="总开关">
<n-switch v-model:value="setting.https" />
</n-form-item-gi>
<n-form-item-gi v-if="setting.https" :span="12" label="使用已有证书">
@@ -311,7 +314,7 @@ const onCreateListen = () => {
</n-form-item-gi>
</n-grid>
</n-form>
<n-form inline>
<n-form inline v-if="setting.https">
<n-form-item label="HSTS">
<n-switch v-model:value="setting.hsts" />
</n-form-item>
@@ -322,12 +325,13 @@ const onCreateListen = () => {
<n-switch v-model:value="setting.ocsp" />
</n-form-item>
</n-form>
<n-form>
<n-form v-if="setting.https">
<n-form-item label="证书">
<n-input
v-model:value="setting.ssl_certificate"
type="textarea"
placeholder="输入 PEM 证书文件的内容"
:autosize="{ minRows: 10, maxRows: 15 }"
/>
</n-form-item>
<n-form-item label="私钥">
@@ -335,6 +339,7 @@ const onCreateListen = () => {
v-model:value="setting.ssl_certificate_key"
type="textarea"
placeholder="输入 KEY 私钥文件的内容"
:autosize="{ minRows: 10, maxRows: 15 }"
/>
</n-form-item>
</n-form>
@@ -398,6 +403,18 @@ const onCreateListen = () => {
<realtime-log :path="setting.log" />
</n-flex>
</n-tab-pane>
<n-tab-pane name="error_log" tab="错误日志">
<n-flex vertical>
<n-flex flex items-center>
<n-alert type="warning" w-full>
全部日志可通过下载文件
<n-tag>{{ setting.error_log }}</n-tag>
查看
</n-alert>
</n-flex>
<realtime-log :path="setting.error_log" />
</n-flex>
</n-tab-pane>
</n-tabs>
</common-page>
</template>

View File

@@ -4,17 +4,7 @@ defineOptions({
})
import Editor from '@guolao/vue-monaco-editor'
import {
NButton,
NCheckbox,
NDataTable,
NFlex,
NInput,
NPopconfirm,
NSpace,
NSwitch,
NTag
} from 'naive-ui'
import { NButton, NCheckbox, NDataTable, NFlex, NInput, NPopconfirm, NSwitch, NTag } from 'naive-ui'
import { useI18n } from 'vue-i18n'
import dashboard from '@/api/panel/dashboard'
@@ -344,23 +334,21 @@ onMounted(() => {
<template>
<common-page show-footer>
<n-flex vertical size="large">
<n-card rounded-10>
<n-space>
<n-button type="primary" @click="createModal = true">
{{ $t('websiteIndex.create.trigger') }}
</n-button>
<n-popconfirm @positive-click="bulkDelete">
<template #trigger>
<n-button type="error"> 批量删除 </n-button>
</template>
这会删除网站目录但不会删除同名数据库确定删除选中的网站吗
</n-popconfirm>
<n-button type="warning" @click="editDefaultPageModal = true">
{{ $t('websiteIndex.edit.trigger') }}
</n-button>
</n-space>
</n-card>
<n-flex vertical :size="20">
<n-flex>
<n-button type="primary" @click="createModal = true">
{{ $t('websiteIndex.create.trigger') }}
</n-button>
<n-popconfirm @positive-click="bulkDelete">
<template #trigger>
<n-button type="error"> 批量删除 </n-button>
</template>
这会删除网站目录但不会删除同名数据库确定删除选中的网站吗
</n-popconfirm>
<n-button type="warning" @click="editDefaultPageModal = true">
{{ $t('websiteIndex.edit.trigger') }}
</n-button>
</n-flex>
<n-data-table
striped
remote