2
0
mirror of https://github.com/acepanel/panel.git synced 2026-02-04 14:57:16 +08:00

feat: 重构证书组件

This commit is contained in:
耗子
2024-10-24 01:48:57 +08:00
parent 0b425f09ee
commit 6050bf611b
12 changed files with 498 additions and 401 deletions

View File

@@ -15,7 +15,7 @@ export default {
// ACME 账号详情
accountInfo: (id: number): Promise<AxiosResponse<any>> => request.get(`/cert/account/${id}`),
// ACME 账号添加
accountAdd: (data: any): Promise<AxiosResponse<any>> => request.post('/cert/account', data),
accountCreate: (data: any): Promise<AxiosResponse<any>> => request.post('/cert/account', data),
// ACME 账号更新
accountUpdate: (id: number, data: any): Promise<AxiosResponse<any>> =>
request.put(`/cert/account/${id}`, data),
@@ -27,7 +27,7 @@ export default {
// DNS 记录详情
dnsInfo: (id: number): Promise<AxiosResponse<any>> => request.get(`/cert/dns/${id}`),
// DNS 记录添加
dnsAdd: (data: any): Promise<AxiosResponse<any>> => request.post('/cert/dns', data),
dnsCreate: (data: any): Promise<AxiosResponse<any>> => request.post('/cert/dns', data),
// DNS 记录更新
dnsUpdate: (id: number, data: any): Promise<AxiosResponse<any>> =>
request.put(`/cert/dns/${id}`, data),
@@ -39,7 +39,7 @@ export default {
// 证书详情
certInfo: (id: number): Promise<AxiosResponse<any>> => request.get(`/cert/cert/${id}`),
// 证书添加
certAdd: (data: any): Promise<AxiosResponse<any>> => request.post('/cert/cert', data),
certCreate: (data: any): Promise<AxiosResponse<any>> => request.post('/cert/cert', data),
// 证书更新
certUpdate: (id: number, data: any): Promise<AxiosResponse<any>> =>
request.put(`/cert/cert/${id}`, data),

View File

@@ -243,12 +243,10 @@ onMounted(() => {
<template>
<common-page show-footer>
<template #action>
<div flex items-center>
<n-button type="primary" @click="handleUpdateCache">
<TheIcon :size="18" icon="material-symbols:refresh" />
{{ $t('appIndex.buttons.updateCache') }}
</n-button>
</div>
<n-button type="primary" @click="handleUpdateCache">
<TheIcon :size="18" icon="material-symbols:refresh" />
{{ $t('appIndex.buttons.updateCache') }}
</n-button>
</template>
<n-flex vertical>
<n-alert type="warning">{{ $t('appIndex.alerts.warning') }}</n-alert>

View File

@@ -12,14 +12,15 @@ import {
import cert from '@/api/panel/cert'
import type { Account } from '@/views/cert/types'
let messageReactive: MessageReactive | null = null
const addAccountModel = ref<any>({
hmac_encoded: '',
email: '',
kid: '',
key_type: 'P256',
ca: 'googlecn'
const props = defineProps({
caProviders: Array<any>,
algorithms: Array<any>
})
const { caProviders, algorithms } = toRefs(props)
let messageReactive: MessageReactive | null = null
const updateAccountModel = ref<any>({
hmac_encoded: '',
email: '',
@@ -27,17 +28,9 @@ const updateAccountModel = ref<any>({
key_type: 'P256',
ca: 'googlecn'
})
const addAccountModal = ref(false)
const updateAccountModal = ref(false)
const updateAccount = ref<any>()
const showEAB = computed(() => {
return addAccountModel.value.ca === 'google' || addAccountModel.value.ca === 'sslcom'
})
const caProviders = ref<any>([])
const algorithms = ref<any>([])
const accountColumns: any = [
{
title: '邮箱',
@@ -61,7 +54,7 @@ const accountColumns: any = [
},
{
default: () => {
return caProviders.value.find((item: any) => item.value === row.ca)?.label
return caProviders?.value?.find((item: any) => item.value === row.ca)?.label
}
}
)
@@ -164,20 +157,6 @@ const getAccountList = async (page: number, limit: number) => {
return data
}
const handleAddAccount = async () => {
messageReactive = window.$message.loading('正在向 CA 注册账号,请耐心等待', {
duration: 0
})
await cert.accountAdd(addAccountModel.value)
messageReactive.destroy()
window.$message.success('添加成功')
addAccountModal.value = false
onAccountPageChange(1)
addAccountModel.value.email = ''
addAccountModel.value.hmac_encoded = ''
addAccountModel.value.kid = ''
}
const handleUpdateAccount = async () => {
messageReactive = window.$message.loading('正在向 CA 注册账号,请耐心等待', {
duration: 0
@@ -193,23 +172,12 @@ const handleUpdateAccount = async () => {
}
onMounted(() => {
cert.caProviders().then((res) => {
caProviders.value = res.data
})
cert.algorithms().then((res) => {
algorithms.value = res.data
})
onAccountPageChange(1)
})
</script>
<template>
<n-space vertical size="large">
<n-card rounded-10>
<n-space>
<n-button type="primary" @click="addAccountModal = true"> 添加账号 </n-button>
</n-space>
</n-card>
<n-data-table
striped
remote
@@ -223,65 +191,6 @@ onMounted(() => {
@update:page-size="onAccountPageSizeChange"
/>
</n-space>
<n-modal
v-model:show="addAccountModal"
preset="card"
title="添加账号"
style="width: 60vw"
size="huge"
:bordered="false"
:segmented="false"
>
<n-space vertical>
<n-alert type="info"> Google 和 SSL.com 需要先去官网获得 KID 和 HMAC 并填入 </n-alert>
<n-alert type="warning">
境内无法使用 Google其他 CA 视网络情况而定,建议使用 GoogleCN 或 Let's Encrypt
</n-alert>
<n-form :model="addAccountModel">
<n-form-item path="ca" label="CA">
<n-select
v-model:value="addAccountModel.ca"
placeholder="选择 CA"
clearable
:options="caProviders"
/>
</n-form-item>
<n-form-item path="key_type" label="密钥类型">
<n-select
v-model:value="addAccountModel.key_type"
placeholder="选择密钥类型"
clearable
:options="algorithms"
/>
</n-form-item>
<n-form-item path="email" label="邮箱">
<n-input
v-model:value="addAccountModel.email"
type="text"
@keydown.enter.prevent
placeholder="输入邮箱地址"
/>
</n-form-item>
<n-form-item v-if="showEAB" path="kid" label="KID">
<n-input
v-model:value="addAccountModel.kid"
type="text"
@keydown.enter.prevent
placeholder="输入 KID"
/>
</n-form-item>
<n-form-item v-if="showEAB" path="hmac_encoded" label="HMAC">
<n-input
v-model:value="addAccountModel.hmac_encoded"
type="text"
@keydown.enter.prevent
placeholder="输入 HMAC"
/>
</n-form-item>
</n-form>
<n-button type="info" block @click="handleAddAccount">提交</n-button>
</n-space>
</n-modal>
<n-modal
v-model:show="updateAccountModal"
preset="card"

View File

@@ -2,20 +2,20 @@
import Editor from '@guolao/vue-monaco-editor'
import { NButton, NDataTable, NPopconfirm, NSpace, NSwitch, NTable, NTag } from 'naive-ui'
import app from '@/api/panel/app'
import cert from '@/api/panel/cert'
import website from '@/api/panel/website'
import type { Cert } from '@/views/cert/types'
let messageReactive: any
const addCertModel = ref<any>({
domains: [],
dns_id: 0,
type: 'P256',
account_id: null,
website_id: 0,
auto_renew: true
const props = defineProps({
algorithms: Array<any>,
websites: Array<any>,
accounts: Array<any>,
dns: Array<any>
})
const { algorithms, websites, accounts, dns } = toRefs(props)
let messageReactive: any
const updateCertModel = ref<any>({
domains: [],
dns_id: 0,
@@ -24,7 +24,6 @@ const updateCertModel = ref<any>({
website_id: 0,
auto_renew: true
})
const addCertModal = ref(false)
const updateCertModal = ref(false)
const updateCert = ref<any>()
const showModal = ref(false)
@@ -38,11 +37,6 @@ const deployCertModel = ref<any>({
website_id: 0
})
const algorithms = ref<any>([])
const websites = ref<any>([])
const dns = ref<any>([])
const accounts = ref<any>([])
const certColumns: any = [
{
title: '域名',
@@ -398,20 +392,6 @@ const getCertList = async (page: number, limit: number) => {
return data
}
const handleAddCert = async () => {
await cert.certAdd(addCertModel.value)
window.$message.success('添加成功')
addCertModal.value = false
onCertPageChange(1)
addCertModel.value.domains = []
addCertModel.value.dns_id = 0
addCertModel.value.type = 'P256'
addCertModel.value.account_id = 0
addCertModel.value.website_id = 0
addCertModel.value.auto_renew = true
await getAsyncData()
}
const handleUpdateCert = async () => {
await cert.certUpdate(updateCert.value, updateCertModel.value)
window.$message.success('更新成功')
@@ -423,7 +403,6 @@ const handleUpdateCert = async () => {
updateCertModel.value.account_id = 0
updateCertModel.value.website_id = 0
updateCertModel.value.auto_renew = true
await getAsyncData()
}
const handleDeployCert = async () => {
@@ -435,68 +414,18 @@ const handleDeployCert = async () => {
onCertPageChange(1)
}
const getAsyncData = async () => {
const { data: algorithmData } = await cert.algorithms()
algorithms.value = algorithmData
websites.value = []
websites.value.push({
label: '无',
value: 0
})
app.isInstalled('nginx').then(async (res) => {
if (res.data.installed) {
const { data: websiteData } = await website.list(1, 10000)
for (const item of websiteData.items) {
websites.value.push({
label: item.name,
value: item.id
})
}
}
})
const { data: dnsData } = await cert.dns(1, 10000)
dns.value = []
dns.value.push({
label: '无',
value: 0
})
for (const item of dnsData.items) {
dns.value.push({
label: item.name,
value: item.id
})
}
const { data: accountData } = await cert.accounts(1, 10000)
accounts.value = []
for (const item of accountData.items) {
accounts.value.push({
label: item.email,
value: item.id
})
}
}
const handleShowModalClose = () => {
showCertModel.value.cert = ''
showCertModel.value.key = ''
}
onMounted(() => {
getAsyncData()
onCertPageChange(1)
})
</script>
<template>
<n-space vertical size="large">
<n-card rounded-10>
<n-space>
<n-button type="primary" @click="addCertModal = true"> 添加证书 </n-button>
</n-space>
</n-card>
<n-data-table
striped
remote
@@ -510,65 +439,6 @@ onMounted(() => {
@update:page-size="onCertPageSizeChange"
/>
</n-space>
<n-modal
v-model:show="addCertModal"
preset="card"
title="添加证书"
style="width: 60vw"
size="huge"
:bordered="false"
:segmented="false"
>
<n-space vertical>
<n-alert type="info">
可以通过选择网站 / DNS 中的任意一项来自动签发和部署证书,也可以手动输入域名并设置 DNS
解析来签发证书
</n-alert>
<n-form :model="addCertModel">
<n-form-item label="域名">
<n-dynamic-input
v-model:value="addCertModel.domains"
placeholder="example.com"
:min="1"
show-sort-button
/>
</n-form-item>
<n-form-item path="type" label="密钥类型">
<n-select
v-model:value="addCertModel.type"
placeholder="选择密钥类型"
clearable
:options="algorithms"
/>
</n-form-item>
<n-form-item path="website_id" label="网站">
<n-select
v-model:value="addCertModel.website_id"
placeholder="选择用于部署证书的网站"
clearable
:options="websites"
/>
</n-form-item>
<n-form-item path="account_id" label="账号">
<n-select
v-model:value="addCertModel.account_id"
placeholder="选择用于签发证书的账号"
clearable
:options="accounts"
/>
</n-form-item>
<n-form-item path="account_id" label="DNS">
<n-select
v-model:value="addCertModel.dns_id"
placeholder="选择用于签发证书的DNS"
clearable
:options="dns"
/>
</n-form-item>
</n-form>
<n-button type="info" block @click="handleAddCert">提交</n-button>
</n-space>
</n-modal>
<n-modal
v-model:show="updateCertModal"
preset="card"

View File

@@ -0,0 +1,109 @@
<script setup lang="ts">
import cert from '@/api/panel/cert'
import type { MessageReactive } from 'naive-ui'
import { NButton, NInput, NSpace } from 'naive-ui'
const show = defineModel<boolean>('show', { type: Boolean, required: true })
const props = defineProps({
caProviders: Array<any>,
algorithms: Array<any>
})
const { caProviders, algorithms } = toRefs(props)
let messageReactive: MessageReactive | null = null
const model = ref<any>({
hmac_encoded: '',
email: '',
kid: '',
key_type: 'P256',
ca: 'googlecn'
})
const showEAB = computed(() => {
return model.value.ca === 'google' || model.value.ca === 'sslcom'
})
const handleCreateAccount = async () => {
messageReactive = window.$message.loading('正在向 CA 注册账号,请耐心等待', {
duration: 0
})
cert
.accountCreate(model.value)
.then(() => {
window.$message.success('创建成功')
model.value.email = ''
model.value.hmac_encoded = ''
model.value.kid = ''
})
.finally(() => {
messageReactive?.destroy()
})
}
</script>
<template>
<n-modal
v-model:show="show"
preset="card"
title="创建账号"
style="width: 60vw"
size="huge"
:bordered="false"
:segmented="false"
>
<n-space vertical>
<n-alert type="info"> Google SSL.com 需要先去官网获得 KID HMAC 并填入 </n-alert>
<n-alert type="warning">
境内无法使用 Google其他 CA 视网络情况而定建议使用 GoogleCN Let's Encrypt
</n-alert>
<n-form :model="model">
<n-form-item path="ca" label="CA">
<n-select
v-model:value="model.ca"
placeholder="选择 CA"
clearable
:options="caProviders"
/>
</n-form-item>
<n-form-item path="key_type" label="密钥类型">
<n-select
v-model:value="model.key_type"
placeholder="选择密钥类型"
clearable
:options="algorithms"
/>
</n-form-item>
<n-form-item path="email" label="邮箱">
<n-input
v-model:value="model.email"
type="text"
@keydown.enter.prevent
placeholder="输入邮箱地址"
/>
</n-form-item>
<n-form-item v-if="showEAB" path="kid" label="KID">
<n-input
v-model:value="model.kid"
type="text"
@keydown.enter.prevent
placeholder="输入 KID"
/>
</n-form-item>
<n-form-item v-if="showEAB" path="hmac_encoded" label="HMAC">
<n-input
v-model:value="model.hmac_encoded"
type="text"
@keydown.enter.prevent
placeholder="输入 HMAC"
/>
</n-form-item>
</n-form>
<n-button type="info" block @click="handleCreateAccount">提交</n-button>
</n-space>
</n-modal>
</template>
<style scoped lang="scss"></style>

View File

@@ -0,0 +1,100 @@
<script setup lang="ts">
import cert from '@/api/panel/cert'
import { NButton, NSpace } from 'naive-ui'
const show = defineModel<boolean>('show', { type: Boolean, required: true })
const props = defineProps({
algorithms: Array<any>,
websites: Array<any>,
accounts: Array<any>,
dns: Array<any>
})
const { algorithms, websites, accounts, dns } = toRefs(props)
const model = ref<any>({
domains: [],
dns_id: 0,
type: 'P256',
account_id: null,
website_id: 0,
auto_renew: true
})
const handleCreateCert = async () => {
await cert.certCreate(model.value)
window.$message.success('创建成功')
model.value = false
model.value.domains = []
model.value.dns_id = 0
model.value.type = 'P256'
model.value.account_id = 0
model.value.website_id = 0
model.value.auto_renew = true
}
</script>
<template>
<n-modal
v-model:show="show"
preset="card"
title="创建证书"
style="width: 60vw"
size="huge"
:bordered="false"
:segmented="false"
>
<n-space vertical>
<n-alert type="info">
可以通过选择网站 / DNS 中的任意一项来自动签发和部署证书也可以手动输入域名并设置 DNS
解析来签发证书
</n-alert>
<n-form :model="model">
<n-form-item label="域名">
<n-dynamic-input
v-model:value="model.domains"
placeholder="example.com"
:min="1"
show-sort-button
/>
</n-form-item>
<n-form-item path="type" label="密钥类型">
<n-select
v-model:value="model.type"
placeholder="选择密钥类型"
clearable
:options="algorithms"
/>
</n-form-item>
<n-form-item path="website_id" label="网站">
<n-select
v-model:value="model.website_id"
placeholder="选择用于部署证书的网站"
clearable
:options="websites"
/>
</n-form-item>
<n-form-item path="account_id" label="账号">
<n-select
v-model:value="model.account_id"
placeholder="选择用于签发证书的账号"
clearable
:options="accounts"
/>
</n-form-item>
<n-form-item path="account_id" label="DNS">
<n-select
v-model:value="model.dns_id"
placeholder="选择用于签发证书的DNS"
clearable
:options="dns"
/>
</n-form-item>
</n-form>
<n-button type="info" block @click="handleCreateCert">提交</n-button>
</n-space>
</n-modal>
</template>
<style scoped lang="scss"></style>

View File

@@ -0,0 +1,122 @@
<script setup lang="ts">
import cert from '@/api/panel/cert'
import { NButton, NInput, NSpace } from 'naive-ui'
const show = defineModel<boolean>('show', { type: Boolean, required: true })
const props = defineProps({
dnsProviders: Array<any>
})
const { dnsProviders } = toRefs(props)
const model = ref<any>({
data: {
ak: '',
sk: ''
},
type: 'aliyun',
name: ''
})
const handleCreateDNS = async () => {
await cert.dnsCreate(model.value)
window.$message.success('创建成功')
show.value = false
model.value.data.ak = ''
model.value.data.sk = ''
model.value.name = ''
}
</script>
<template>
<n-modal
v-model:show="show"
preset="card"
title="创建 DNS"
style="width: 60vw"
size="huge"
:bordered="false"
:segmented="false"
>
<n-space vertical>
<n-form :model="model">
<n-form-item path="name" label="备注名称">
<n-input
v-model:value="model.name"
type="text"
@keydown.enter.prevent
placeholder="输入备注名称"
/>
</n-form-item>
<n-form-item path="type" label="DNS">
<n-select
v-model:value="model.type"
placeholder="选择 DNS"
clearable
:options="dnsProviders"
/>
</n-form-item>
<n-form-item v-if="model.type == 'aliyun'" path="ak" label="Access Key">
<n-input
v-model:value="model.data.ak"
type="text"
@keydown.enter.prevent
placeholder="输入阿里云 Access Key"
/>
</n-form-item>
<n-form-item v-if="model.type == 'aliyun'" path="sk" label="Secret Key">
<n-input
v-model:value="model.data.sk"
type="text"
@keydown.enter.prevent
placeholder="输入阿里云 Secret Key"
/>
</n-form-item>
<n-form-item v-if="model.type == 'tencent'" path="ak" label="SecretId">
<n-input
v-model:value="model.data.ak"
type="text"
@keydown.enter.prevent
placeholder="输入腾讯云 SecretId"
/>
</n-form-item>
<n-form-item v-if="model.type == 'tencent'" path="sk" label="SecretKey">
<n-input
v-model:value="model.data.sk"
type="text"
@keydown.enter.prevent
placeholder="输入腾讯云 SecretKey"
/>
</n-form-item>
<n-form-item v-if="model.type == 'huawei'" path="ak" label="AccessKeyId">
<n-input
v-model:value="model.data.ak"
type="text"
@keydown.enter.prevent
placeholder="输入华为云 AccessKeyId"
/>
</n-form-item>
<n-form-item v-if="model.type == 'huawei'" path="sk" label="SecretAccessKey">
<n-input
v-model:value="model.data.sk"
type="text"
@keydown.enter.prevent
placeholder="输入华为云 SecretAccessKey"
/>
</n-form-item>
<n-form-item v-if="model.type == 'cloudflare'" path="ak" label="API Key">
<n-input
v-model:value="model.data.ak"
type="text"
@keydown.enter.prevent
placeholder="输入 Cloudflare API Key"
/>
</n-form-item>
</n-form>
<n-button type="info" block @click="handleCreateDNS">提交</n-button>
</n-space>
</n-modal>
</template>
<style scoped lang="scss"></style>

View File

@@ -4,14 +4,12 @@ import { NButton, NDataTable, NInput, NPopconfirm, NSpace, NTag } from 'naive-ui
import cert from '@/api/panel/cert'
import type { DNS } from '@/views/cert/types'
const addDNSModel = ref<any>({
data: {
ak: '',
sk: ''
},
type: 'aliyun',
name: ''
const props = defineProps({
dnsProviders: Array<any>
})
const { dnsProviders } = toRefs(props)
const updateDNSModel = ref<any>({
data: {
ak: '',
@@ -20,12 +18,9 @@ const updateDNSModel = ref<any>({
type: 'aliyun',
name: ''
})
const addDNSModal = ref(false)
const updateDNSModal = ref(false)
const updateDNS = ref<any>()
const dnsProviders = ref<any>([])
const dnsColumns: any = [
{
title: '备注名称',
@@ -155,16 +150,6 @@ const getDnsList = async (page: number, limit: number) => {
return data
}
const handleAddDNS = async () => {
await cert.dnsAdd(addDNSModel.value)
window.$message.success('添加成功')
addDNSModal.value = false
onDnsPageChange(1)
addDNSModel.value.data.ak = ''
addDNSModel.value.data.sk = ''
addDNSModel.value.name = ''
}
const handleUpdateDNS = async () => {
await cert.dnsUpdate(updateDNS.value, updateDNSModel.value)
window.$message.success('更新成功')
@@ -176,20 +161,12 @@ const handleUpdateDNS = async () => {
}
onMounted(async () => {
cert.dnsProviders().then((res) => {
dnsProviders.value = res.data
})
onDnsPageChange(1)
})
</script>
<template>
<n-space vertical size="large">
<n-card rounded-10>
<n-space>
<n-button type="primary" @click="addDNSModal = true"> 添加 DNS </n-button>
</n-space>
</n-card>
<n-data-table
striped
remote
@@ -203,93 +180,6 @@ onMounted(async () => {
@update:page-size="onDnsPageSizeChange"
/>
</n-space>
<n-modal
v-model:show="addDNSModal"
preset="card"
title="添加 DNS"
style="width: 60vw"
size="huge"
:bordered="false"
:segmented="false"
>
<n-space vertical>
<n-form :model="addDNSModel">
<n-form-item path="name" label="备注名称">
<n-input
v-model:value="addDNSModel.name"
type="text"
@keydown.enter.prevent
placeholder="输入备注名称"
/>
</n-form-item>
<n-form-item path="type" label="DNS">
<n-select
v-model:value="addDNSModel.type"
placeholder="选择 DNS"
clearable
:options="dnsProviders"
/>
</n-form-item>
<n-form-item v-if="addDNSModel.type == 'aliyun'" path="ak" label="Access Key">
<n-input
v-model:value="addDNSModel.data.ak"
type="text"
@keydown.enter.prevent
placeholder="输入阿里云 Access Key"
/>
</n-form-item>
<n-form-item v-if="addDNSModel.type == 'aliyun'" path="sk" label="Secret Key">
<n-input
v-model:value="addDNSModel.data.sk"
type="text"
@keydown.enter.prevent
placeholder="输入阿里云 Secret Key"
/>
</n-form-item>
<n-form-item v-if="addDNSModel.type == 'tencent'" path="ak" label="SecretId">
<n-input
v-model:value="addDNSModel.data.ak"
type="text"
@keydown.enter.prevent
placeholder="输入腾讯云 SecretId"
/>
</n-form-item>
<n-form-item v-if="addDNSModel.type == 'tencent'" path="sk" label="SecretKey">
<n-input
v-model:value="addDNSModel.data.sk"
type="text"
@keydown.enter.prevent
placeholder="输入腾讯云 SecretKey"
/>
</n-form-item>
<n-form-item v-if="addDNSModel.type == 'huawei'" path="ak" label="AccessKeyId">
<n-input
v-model:value="addDNSModel.data.ak"
type="text"
@keydown.enter.prevent
placeholder="输入华为云 AccessKeyId"
/>
</n-form-item>
<n-form-item v-if="addDNSModel.type == 'huawei'" path="sk" label="SecretAccessKey">
<n-input
v-model:value="addDNSModel.data.sk"
type="text"
@keydown.enter.prevent
placeholder="输入华为云 SecretAccessKey"
/>
</n-form-item>
<n-form-item v-if="addDNSModel.type == 'cloudflare'" path="ak" label="API Key">
<n-input
v-model:value="addDNSModel.data.ak"
type="text"
@keydown.enter.prevent
placeholder="输入 Cloudflare API Key"
/>
</n-form-item>
</n-form>
<n-button type="info" block @click="handleAddDNS">提交</n-button>
</n-space>
</n-modal>
<n-modal
v-model:show="updateDNSModal"
preset="card"

View File

@@ -3,25 +3,125 @@ defineOptions({
name: 'cert-index'
})
import { NButton } from 'naive-ui'
import app from '@/api/panel/app'
import cert from '@/api/panel/cert'
import website from '@/api/panel/website'
import AccountView from '@/views/cert/AccountView.vue'
import CertView from '@/views/cert/CertView.vue'
import CreateAccountModal from '@/views/cert/CreateAccountModal.vue'
import CreateCertModal from '@/views/cert/CreateCertModal.vue'
import CreateDnsModal from '@/views/cert/CreateDnsModal.vue'
import DnsView from '@/views/cert/DnsView.vue'
const currentTab = ref('cert')
const createDNS = ref(false)
const createCert = ref(false)
const createAccount = ref(false)
const algorithms = ref<any>([])
const websites = ref<any>([])
const dns = ref<any>([])
const accounts = ref<any>([])
const dnsProviders = ref<any>([])
const caProviders = ref<any>([])
const getAsyncData = async () => {
const { data: algorithmData } = await cert.algorithms()
algorithms.value = algorithmData
websites.value = []
websites.value.push({
label: '无',
value: 0
})
app.isInstalled('nginx').then(async (res) => {
if (res.data.installed) {
const { data: websiteData } = await website.list(1, 10000)
for (const item of websiteData.items) {
websites.value.push({
label: item.name,
value: item.id
})
}
}
})
const { data: dnsData } = await cert.dns(1, 10000)
dns.value = []
dns.value.push({
label: '无',
value: 0
})
for (const item of dnsData.items) {
dns.value.push({
label: item.name,
value: item.id
})
}
const { data: accountData } = await cert.accounts(1, 10000)
accounts.value = []
for (const item of accountData.items) {
accounts.value.push({
label: item.email,
value: item.id
})
}
const { data: dnsProviderData } = await cert.dnsProviders()
dnsProviders.value = dnsProviderData
const { data: caProviderData } = await cert.caProviders()
caProviders.value = caProviderData
}
onMounted(() => {
getAsyncData()
})
</script>
<template>
<common-page show-footer>
<template #action>
<n-button v-if="currentTab == 'cert'" type="primary" @click="createCert = true">
<TheIcon :size="18" icon="material-symbols:add" />
创建证书
</n-button>
<n-button v-if="currentTab == 'user'" type="primary" @click="createAccount = true">
<TheIcon :size="18" icon="material-symbols:add" />
创建账号
</n-button>
<n-button v-if="currentTab == 'dns'" type="primary" @click="createDNS = true">
<TheIcon :size="18" icon="material-symbols:add" />
创建 DNS
</n-button>
</template>
<n-tabs v-model:value="currentTab" type="line" animated>
<n-tab-pane name="cert" tab="证书列表">
<cert-view />
<cert-view :accounts="accounts" :algorithms="algorithms" :websites="websites" :dns="dns" />
</n-tab-pane>
<n-tab-pane name="user" tab="账号列表">
<account-view />
<account-view :ca-providers="caProviders" :algorithms="algorithms" />
</n-tab-pane>
<n-tab-pane name="dns" tab="DNS 列表">
<dns-view />
<dns-view :dns-providers="dnsProviders" />
</n-tab-pane>
</n-tabs>
</common-page>
<create-cert-modal
v-model:show="createCert"
:accounts="accounts"
:algorithms="algorithms"
:websites="websites"
:dns="dns"
/>
<create-dns-modal v-model:show="createDNS" :dns-providers="dnsProviders" />
<create-account-modal
v-model:show="createAccount"
:ca-providers="caProviders"
:algorithms="algorithms"
/>
</template>

View File

@@ -234,12 +234,10 @@ onUnmounted(() => {
<template>
<common-page show-footer>
<template #action>
<div flex items-center>
<n-button type="primary" @click="create = true">
<TheIcon :size="18" icon="material-symbols:add" />
创建主机
</n-button>
</div>
<n-button type="primary" @click="create = true">
<TheIcon :size="18" icon="material-symbols:add" />
创建主机
</n-button>
</template>
<n-layout has-sider sider-placement="right">
<n-layout content-style="overflow: visible" bg-hex-111>

View File

@@ -3,19 +3,17 @@ import cronstrue from 'cronstrue'
import 'cronstrue/locales/zh_CN'
import Editor from '@guolao/vue-monaco-editor'
import { NButton, NDataTable, NFlex, NInput, NPopconfirm, NSwitch, NTag } from 'naive-ui'
import { NButton, NDataTable, NInput, NPopconfirm, NSwitch, NTag } from 'naive-ui'
import cron from '@/api/panel/cron'
import file from '@/api/panel/file'
import { formatDateTime, renderIcon } from '@/utils'
import CreateModal from '@/views/task/CreateModal.vue'
import type { CronTask } from '@/views/task/types'
import { CronNaive } from '@vue-js-cron/naive-ui'
const logPath = ref('')
const logModal = ref(false)
const editModal = ref(false)
const create = ref(false)
const columns: any = [
{ type: 'selection', fixed: 'left' },
@@ -232,36 +230,27 @@ const saveTaskEdit = async () => {
})
}
watch(create, () => {
onPageChange(pagination.page)
})
onMounted(() => {
onPageChange(pagination.page)
})
</script>
<template>
<n-flex vertical>
<n-card flex-1 rounded-10>
<n-button type="primary" @click="create = true">创建计划任务</n-button>
</n-card>
<n-card flex-1 rounded-10>
<n-data-table
striped
remote
:scroll-x="1300"
:data="data"
:columns="columns"
:row-key="(row: any) => row.id"
:pagination="pagination"
:bordered="false"
:loading="false"
@update:page="onPageChange"
@update:page-size="onPageSizeChange"
/>
</n-card>
</n-flex>
<n-card flex-1 rounded-10>
<n-data-table
striped
remote
:scroll-x="1300"
:data="data"
:columns="columns"
:row-key="(row: any) => row.id"
:pagination="pagination"
:bordered="false"
:loading="false"
@update:page="onPageChange"
@update:page-size="onPageSizeChange"
/>
</n-card>
<realtime-log-modal v-model:show="logModal" :path="logPath" />
<n-modal
v-model:show="editModal"
@@ -294,5 +283,4 @@ onMounted(() => {
}"
/>
</n-modal>
<create-modal v-model:show="create" />
</template>

View File

@@ -1,16 +1,28 @@
<script setup lang="ts">
import { NButton } from 'naive-ui'
defineOptions({
name: 'task-index'
})
import TheIcon from '@/components/custom/TheIcon.vue'
import CreateModal from '@/views/task/CreateModal.vue'
import CronView from '@/views/task/CronView.vue'
import TaskView from '@/views/task/TaskView.vue'
const current = ref('cron')
const create = ref(false)
</script>
<template>
<common-page show-footer>
<template #action>
<n-button v-if="current == 'cron'" type="primary" @click="create = true">
<TheIcon :size="18" icon="material-symbols:add" />
创建任务
</n-button>
</template>
<n-tabs v-model:value="current" type="line" animated size="large">
<n-tab-pane name="cron" tab="计划任务">
<cron-view />
@@ -20,6 +32,7 @@ const current = ref('cron')
</n-tab-pane>
</n-tabs>
</common-page>
<create-modal v-model:show="create" />
</template>
<style scoped lang="scss"></style>