mirror of
https://gitee.com/mirrors/AllinSSL.git
synced 2026-03-10 00:31:10 +08:00
【新增】百度云DNS解析功能和宝塔waf部署功能
【新增】本机部署方式 【修复】已知问题
This commit is contained in:
@@ -10,7 +10,17 @@ interface DnsProviderOption {
|
||||
type: string
|
||||
}
|
||||
|
||||
type DnsProviderType = 'btpanel' | 'aliyun' | 'ssh' | 'tencentcloud' | '1panel' | 'dns' | ''
|
||||
type DnsProviderType =
|
||||
| 'aliyun'
|
||||
| 'tencentcloud'
|
||||
| 'baidu'
|
||||
| 'huaweicloud'
|
||||
| 'cloudflare'
|
||||
| 'dns'
|
||||
| 'btpanel'
|
||||
| '1panel'
|
||||
| 'ssh'
|
||||
| ''
|
||||
|
||||
interface DnsProviderSelectProps {
|
||||
// 表单类型,用于获取不同的下拉列表
|
||||
|
||||
@@ -1,4 +1,17 @@
|
||||
import { NButton, NCard, NStep, NSteps, NText, NTooltip } from 'naive-ui'
|
||||
import {
|
||||
NButton,
|
||||
NCard,
|
||||
NStep,
|
||||
NSteps,
|
||||
NText,
|
||||
NTooltip,
|
||||
NTabs,
|
||||
NTabPane,
|
||||
NInput,
|
||||
NDivider,
|
||||
NFormItem,
|
||||
NSwitch,
|
||||
} from 'naive-ui'
|
||||
import { useForm, useFormHooks, useModalClose, useModalOptions, useMessage } from '@baota/naive-ui/hooks'
|
||||
import { useThemeCssVar } from '@baota/naive-ui/theme'
|
||||
import { useError } from '@baota/hooks/error'
|
||||
@@ -7,6 +20,7 @@ import { DeployNodeConfig, DeployNodeInputsConfig } from '@components/flowChart/
|
||||
import { $t } from '@locales/index'
|
||||
import SvgIcon from '@components/svgIcon'
|
||||
import DnsProviderSelect from '@/components/dnsProviderSelect'
|
||||
import SearchOutlined from '@vicons/antd/es/SearchOutlined'
|
||||
|
||||
import styles from './index.module.css'
|
||||
import verifyRules from './verify'
|
||||
@@ -30,6 +44,7 @@ export default defineComponent({
|
||||
fromNodeId: '',
|
||||
name: '',
|
||||
},
|
||||
skip: 1,
|
||||
},
|
||||
}),
|
||||
},
|
||||
@@ -51,47 +66,75 @@ export default defineComponent({
|
||||
|
||||
// 部署类型选项
|
||||
const deployTypeOptions = [
|
||||
{ label: $t('t_5_1744958839222'), value: 'ssh' },
|
||||
{ label: $t('t_10_1745735765165'), value: 'btpanel' },
|
||||
{ label: $t('t_11_1745735766456'), value: 'btpanel-site' },
|
||||
{ label: $t('t_12_1745735765571'), value: '1panel' },
|
||||
{ label: $t('t_13_1745735766084'), value: '1panel-site' },
|
||||
{ label: $t('t_14_1745735766121'), value: 'tencentcloud-cdn' },
|
||||
{ label: $t('t_15_1745735768976'), value: 'tencentcloud-cos' },
|
||||
{ label: $t('t_16_1745735766712'), value: 'aliyun-cdn' },
|
||||
{ label: $t('t_2_1746697487164'), value: 'aliyun-oss' },
|
||||
{ label: $t('t_6_1747271296994'), value: 'localhost', category: 'host', icon: 'ssh' },
|
||||
{ label: $t('t_5_1744958839222'), value: 'ssh', category: 'host', icon: 'ssh' },
|
||||
{ label: $t('t_10_1745735765165'), value: 'btpanel', category: 'btpanel', icon: 'btpanel' },
|
||||
{ label: $t('t_11_1745735766456'), value: 'btpanel-site', category: 'btpanel', icon: 'btpanel' },
|
||||
{ label: $t('t_0_1747215751189'), value: 'btwaf-site', category: 'btpanel', icon: 'btpanel' },
|
||||
{ label: $t('t_12_1745735765571'), value: '1panel', category: '1panel', icon: '1panel' },
|
||||
{ label: $t('t_13_1745735766084'), value: '1panel-site', category: '1panel', icon: '1panel' },
|
||||
{ label: $t('t_14_1745735766121'), value: 'tencentcloud-cdn', category: 'tencentcloud', icon: 'tencentcloud' },
|
||||
{ label: $t('t_15_1745735768976'), value: 'tencentcloud-cos', category: 'tencentcloud', icon: 'tencentcloud' },
|
||||
{ label: $t('t_16_1745735766712'), value: 'aliyun-cdn', category: 'aliyun', icon: 'aliyun' },
|
||||
{ label: $t('t_2_1746697487164'), value: 'aliyun-oss', category: 'aliyun', icon: 'aliyun' },
|
||||
]
|
||||
const certOptions = ref<{ label: string; value: string }[]>([]) // 证书选项
|
||||
const current = ref(1) // 当前步骤
|
||||
const next = ref(true) // 是否是下一步
|
||||
const currentStatus = ref<StepStatus>('process') // 当前步骤状态
|
||||
const currentTab = ref('all') // 当前选中的tab
|
||||
const searchKeyword = ref('') // 搜索关键字
|
||||
|
||||
const param = ref(deepClone(props.node.config)) // 表单参数
|
||||
const localProvider = ref([{ label: $t('本机部署'), value: 'localhost' }]) // 本地提供商
|
||||
const provider = computed(() => {
|
||||
return param.value.provider
|
||||
? $t('t_4_1746858917773') + ':' + deployTypeOptions.find((item) => item.value === param.value.provider)?.label
|
||||
: $t('t_19_1745735766810')
|
||||
})
|
||||
|
||||
// 过滤后的部署类型选项
|
||||
const filteredDeployTypes = computed(() => {
|
||||
let filtered = deployTypeOptions
|
||||
|
||||
// 根据标签过滤
|
||||
if (currentTab.value !== 'all') {
|
||||
filtered = filtered.filter((item) => item.category === currentTab.value)
|
||||
}
|
||||
|
||||
// 根据搜索关键词过滤
|
||||
if (searchKeyword.value) {
|
||||
const keyword = searchKeyword.value.toLowerCase()
|
||||
filtered = filtered.filter(
|
||||
(item) => item.label.toLowerCase().includes(keyword) || item.value.toLowerCase().includes(keyword),
|
||||
)
|
||||
}
|
||||
|
||||
return filtered
|
||||
})
|
||||
|
||||
// 表单配置
|
||||
const formConfig = computed(() => {
|
||||
const config = []
|
||||
config.push(
|
||||
...[
|
||||
{
|
||||
type: 'custom' as const,
|
||||
render: () => {
|
||||
return (
|
||||
<DnsProviderSelect
|
||||
type={param.value.provider}
|
||||
path="provider_id"
|
||||
value={param.value.provider_id}
|
||||
onUpdate:value={(val: { value: number; type: string }) => {
|
||||
param.value.provider_id = val.value
|
||||
}}
|
||||
/>
|
||||
)
|
||||
},
|
||||
},
|
||||
param.value.provider !== 'localhost'
|
||||
? {
|
||||
type: 'custom' as const,
|
||||
render: () => {
|
||||
return (
|
||||
<DnsProviderSelect
|
||||
type={param.value.provider}
|
||||
path="provider_id"
|
||||
value={param.value.provider_id}
|
||||
onUpdate:value={(val: { value: number; type: string }) => {
|
||||
param.value.provider_id = val.value
|
||||
}}
|
||||
/>
|
||||
)
|
||||
},
|
||||
}
|
||||
: useFormSelect($t('主机提供商'), 'provider', localProvider.value, { disabled: true }),
|
||||
],
|
||||
useFormSelect($t('t_1_1745748290291'), 'inputs.fromNodeId', certOptions.value, {
|
||||
onUpdateValue: (val, option: { label: string; value: string }) => {
|
||||
@@ -101,36 +144,38 @@ export default defineComponent({
|
||||
}),
|
||||
)
|
||||
switch (param.value.provider) {
|
||||
case 'localhost':
|
||||
case 'ssh':
|
||||
config.push(
|
||||
...[
|
||||
useFormInput('证书文件路径(仅支持PEM格式)', 'certPath', {
|
||||
useFormInput($t('证书文件路径(仅支持PEM格式)'), 'certPath', {
|
||||
placeholder: $t('t_30_1746667591892'),
|
||||
onInput: (val: string) => (param.value.certPath = val.trim()),
|
||||
}),
|
||||
useFormInput('私钥文件路径', 'keyPath', {
|
||||
useFormInput($t('私钥文件路径'), 'keyPath', {
|
||||
placeholder: $t('t_31_1746667593074'),
|
||||
onInput: (val: string) => (param.value.keyPath = val.trim()),
|
||||
}),
|
||||
useFormTextarea(
|
||||
'前置命令',
|
||||
$t('前置命令(可选)'),
|
||||
'beforeCmd',
|
||||
{ placeholder: $t('t_21_1745735769154') },
|
||||
{ placeholder: $t('t_21_1745735769154'), rows: 2 },
|
||||
{ showRequireMark: false },
|
||||
),
|
||||
useFormTextarea(
|
||||
'后置命令',
|
||||
$t('后置命令(可选)'),
|
||||
'afterCmd',
|
||||
{ placeholder: $t('t_22_1745735767366') },
|
||||
{ placeholder: $t('t_22_1745735767366'), rows: 2 },
|
||||
{ showRequireMark: false },
|
||||
),
|
||||
],
|
||||
)
|
||||
break
|
||||
case 'btwaf-site':
|
||||
case 'btpanel-site':
|
||||
config.push(
|
||||
...[
|
||||
useFormInput('站点名称', 'siteName', {
|
||||
useFormInput($t('站点名称'), 'siteName', {
|
||||
placeholder: $t('t_23_1745735766455'),
|
||||
onInput: (val: string) => (param.value.siteName = val.trim()),
|
||||
}),
|
||||
@@ -140,7 +185,7 @@ export default defineComponent({
|
||||
case '1panel-site':
|
||||
config.push(
|
||||
...[
|
||||
useFormInput('站点ID', 'site_id', {
|
||||
useFormInput($t('站点ID'), 'site_id', {
|
||||
placeholder: $t('t_24_1745735766826'),
|
||||
onInput: (val: string) => (param.value.site_id = val.trim()),
|
||||
}),
|
||||
@@ -151,7 +196,7 @@ export default defineComponent({
|
||||
case 'aliyun-cdn':
|
||||
config.push(
|
||||
...[
|
||||
useFormInput('域名', 'domain', {
|
||||
useFormInput($t('域名'), 'domain', {
|
||||
placeholder: $t('t_0_1744958839535'),
|
||||
onInput: (val: string) => (param.value.domain = val.trim()),
|
||||
}),
|
||||
@@ -162,7 +207,7 @@ export default defineComponent({
|
||||
case 'aliyun-oss':
|
||||
config.push(
|
||||
...[
|
||||
useFormInput('域名', 'domain', {
|
||||
useFormInput($t('域名'), 'domain', {
|
||||
placeholder: $t('t_0_1744958839535'),
|
||||
onInput: (val: string) => (param.value.domain = val.trim()),
|
||||
}),
|
||||
@@ -170,7 +215,7 @@ export default defineComponent({
|
||||
)
|
||||
config.push(
|
||||
...[
|
||||
useFormInput('区域', 'region', {
|
||||
useFormInput($t('区域'), 'region', {
|
||||
placeholder: $t('t_25_1745735766651'),
|
||||
onInput: (val: string) => (param.value.region = val.trim()),
|
||||
}),
|
||||
@@ -178,7 +223,7 @@ export default defineComponent({
|
||||
)
|
||||
config.push(
|
||||
...[
|
||||
useFormInput('存储桶', 'bucket', {
|
||||
useFormInput($t('存储桶'), 'bucket', {
|
||||
placeholder: $t('t_26_1745735767144'),
|
||||
onInput: (val: string) => (param.value.bucket = val.trim()),
|
||||
}),
|
||||
@@ -186,6 +231,25 @@ export default defineComponent({
|
||||
)
|
||||
break
|
||||
}
|
||||
|
||||
config.push({
|
||||
type: 'custom' as const,
|
||||
render: () => {
|
||||
return (
|
||||
<NFormItem label={$t('重复部署')} path="skip">
|
||||
<NText>{$t('当与上次部署的证书相同且上次部署成功时')}</NText>
|
||||
<NSwitch
|
||||
v-model:value={param.value.skip}
|
||||
checkedValue={1}
|
||||
uncheckedValue={0}
|
||||
class="mx-[.5rem] "
|
||||
v-slots={{ checked: () => $t('跳过'), unchecked: () => $t('不跳过') }}
|
||||
/>
|
||||
<NText>{$t('重新部署')}</NText>
|
||||
</NFormItem>
|
||||
)
|
||||
},
|
||||
})
|
||||
return config
|
||||
})
|
||||
|
||||
@@ -195,7 +259,11 @@ export default defineComponent({
|
||||
*/
|
||||
const nextStep = async () => {
|
||||
if (!param.value.provider) return message.error($t('t_0_1746858920894'))
|
||||
|
||||
if (param.value.provider === 'localhost') {
|
||||
delete param.value.provider_id
|
||||
} else {
|
||||
param.value.provider_id = props.node.config.provider_id
|
||||
}
|
||||
// 加载证书来源选项
|
||||
certOptions.value = findApplyUploadNodesUp(props.node.id).map((item) => {
|
||||
return { label: item.name, value: item.id }
|
||||
@@ -240,11 +308,12 @@ export default defineComponent({
|
||||
await example.value?.validate()
|
||||
const tempData = param.value
|
||||
const inputs = tempData.inputs
|
||||
updateNode(props.node.id, { inputs: [inputs], config: {} }, false)
|
||||
delete tempData.inputs
|
||||
// 将输入值直接传递给updateNodeConfig
|
||||
updateNodeConfig(props.node.id, {
|
||||
...tempData,
|
||||
})
|
||||
// 单独更新inputs
|
||||
updateNode(props.node.id, { inputs: [inputs] } as any, false)
|
||||
isRefreshNode.value = props.node.id
|
||||
closeModal()
|
||||
} catch (error) {
|
||||
@@ -256,6 +325,8 @@ export default defineComponent({
|
||||
onMounted(() => {
|
||||
// 隐藏底部按钮
|
||||
modalOptions.value.footer = false
|
||||
// 设置弹窗宽度和高度
|
||||
modalOptions.value.area = [850, 600]
|
||||
// 如果已经选择了部署类型,则跳转到下一步
|
||||
if (param.value.provider) {
|
||||
if (props.node.inputs) param.value.inputs = props.node.inputs[0]
|
||||
@@ -270,25 +341,61 @@ export default defineComponent({
|
||||
<NStep title={$t('t_29_1745735768933')} description={$t('t_2_1745738969878')}></NStep>
|
||||
</NSteps>
|
||||
{current.value === 1 && (
|
||||
<div class={styles.cardContainer}>
|
||||
{deployTypeOptions.map((item) => (
|
||||
<div
|
||||
key={item.value}
|
||||
class={`${styles.optionCard} ${param.value.provider === item.value ? styles.optionCardSelected : ''}`}
|
||||
onClick={() => {
|
||||
param.value.provider = item.value
|
||||
}}
|
||||
<div class={styles.configContainer}>
|
||||
<div class={styles.leftPanel}>
|
||||
<NTabs
|
||||
type="bar"
|
||||
placement="left"
|
||||
value={currentTab.value}
|
||||
onUpdateValue={(val) => (currentTab.value = val)}
|
||||
>
|
||||
<NCard contentClass={styles.cardContent} hoverable bordered={false}>
|
||||
<SvgIcon
|
||||
icon={`resources-${item.value.replace(/-[a-z]+$/, '')}`}
|
||||
size="2rem"
|
||||
class={`${styles.icon} ${param.value.provider === item.value ? styles.iconSelected : ''}`}
|
||||
/>
|
||||
<NText type={param.value.provider === item.value ? 'primary' : 'default'}>{item.label}</NText>
|
||||
</NCard>
|
||||
<NTabPane name="all" tab={$t('t_7_1747271292060')} />
|
||||
<NTabPane name="host" tab={$t('t_1_1745833931535')} />
|
||||
<NTabPane name="btpanel" tab={$t('t_8_1747271290414')} />
|
||||
<NTabPane name="1panel" tab={$t('t_9_1747271284765')} />
|
||||
<NTabPane name="tencentcloud" tab={$t('t_3_1747019616129')} />
|
||||
<NTabPane name="aliyun" tab={$t('t_2_1747019616224')} />
|
||||
</NTabs>
|
||||
</div>
|
||||
<div class={styles.rightPanel}>
|
||||
<div class={styles.searchBar}>
|
||||
<NInput
|
||||
value={searchKeyword.value}
|
||||
onUpdateValue={(val) => (searchKeyword.value = val)}
|
||||
placeholder={$t('搜索部署类型')}
|
||||
clearable
|
||||
>
|
||||
{{
|
||||
suffix: () => (
|
||||
<div class="flex items-center">
|
||||
<SearchOutlined class="text-[var(--text-color-3)] w-[1.6rem] cursor-pointer font-bold" />
|
||||
</div>
|
||||
),
|
||||
}}
|
||||
</NInput>
|
||||
</div>
|
||||
))}
|
||||
<NDivider class="!my-[1rem]" />
|
||||
<div class={styles.cardContainer}>
|
||||
{filteredDeployTypes.value.map((item) => (
|
||||
<div
|
||||
key={item.value}
|
||||
class={`${styles.optionCard} ${param.value.provider === item.value ? styles.optionCardSelected : ''}`}
|
||||
onClick={() => {
|
||||
param.value.provider = item.value
|
||||
}}
|
||||
>
|
||||
<div class={styles.cardContent}>
|
||||
<SvgIcon
|
||||
icon={`resources-${item.icon.replace(/-[a-z]+$/, '')}`}
|
||||
size="2rem"
|
||||
class={`${styles.icon} ${param.value.provider === item.value ? styles.iconSelected : ''}`}
|
||||
/>
|
||||
<NText type={param.value.provider === item.value ? 'primary' : 'default'}>{item.label}</NText>
|
||||
</div>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
{current.value === 2 && (
|
||||
|
||||
@@ -1,13 +1,35 @@
|
||||
/* Deploy Node Drawer Styles */
|
||||
|
||||
/* 整体布局容器 */
|
||||
.configContainer {
|
||||
@apply flex mt-[2.4rem] gap-4;
|
||||
}
|
||||
|
||||
/* 左侧面板样式 */
|
||||
.leftPanel {
|
||||
@apply border-r border-solid;
|
||||
border-color: var(--n-border-color);
|
||||
}
|
||||
|
||||
/* 右侧面板样式 */
|
||||
.rightPanel {
|
||||
@apply flex-1 flex flex-col;
|
||||
}
|
||||
|
||||
/* 搜索栏样式 */
|
||||
.searchBar {
|
||||
@apply w-full mb-[1rem] px-[0.5rem];
|
||||
}
|
||||
|
||||
/* Card container styles */
|
||||
.cardContainer {
|
||||
@apply grid grid-cols-3 gap-4 mt-[2.4rem];
|
||||
@apply grid grid-cols-3 gap-4 mt-[0.5rem] overflow-y-auto px-[0.5rem] h-[28rem];
|
||||
grid-auto-rows: min-content;
|
||||
}
|
||||
|
||||
/* Option card styles */
|
||||
.optionCard {
|
||||
@apply flex items-center justify-center rounded-[0.4rem] transition-all border-[1px] border-transparent;
|
||||
@apply flex items-center justify-center rounded-[0.4rem] transition-all border-[1px] border-transparent h-[6.2rem];
|
||||
border-color: var(--n-border-color);
|
||||
}
|
||||
|
||||
@@ -38,7 +60,7 @@
|
||||
|
||||
/* Card content styles */
|
||||
.cardContent {
|
||||
@apply flex flex-col items-center justify-center p-[4px] cursor-pointer;
|
||||
@apply flex flex-col items-center justify-center p-[4px] cursor-pointer pt-[1rem] text-[1.3rem];
|
||||
}
|
||||
|
||||
/* Icon styles */
|
||||
|
||||
@@ -37,7 +37,7 @@ export default defineComponent({
|
||||
|
||||
// 提示内容
|
||||
const verificationPrompt = computed(() => {
|
||||
console.log(props.node.config.provider, 'validationResult')
|
||||
console.log(validationResult.value, 'validationResult', props.node.config)
|
||||
if (validationResult.value.valid) return <TypeIcon icon={props.node.config.provider} type="success" />
|
||||
return $t('t_9_1745735765287')
|
||||
})
|
||||
|
||||
@@ -147,6 +147,7 @@ nodeOptions[DEPLOY] = () =>
|
||||
config: {
|
||||
provider: '',
|
||||
provider_id: '',
|
||||
skip: 1,
|
||||
inputs: {
|
||||
fromNodeId: '',
|
||||
name: '',
|
||||
|
||||
@@ -29,6 +29,7 @@ export default {
|
||||
config: {
|
||||
provider: '',
|
||||
provider_id: '',
|
||||
skip: 1,
|
||||
inputs: {
|
||||
fromNodeId: '',
|
||||
name: '',
|
||||
|
||||
@@ -231,10 +231,11 @@ export interface DeployConfig<
|
||||
> {
|
||||
provider: T
|
||||
provider_id: string
|
||||
skip: 1 | 0
|
||||
[key: string]: Z
|
||||
}
|
||||
|
||||
export interface DeployPanelConfig {}
|
||||
// export interface DeployPanelConfig {}
|
||||
|
||||
// 部署节点配置(ssh)
|
||||
export interface DeploySSHConfig {
|
||||
@@ -244,6 +245,9 @@ export interface DeploySSHConfig {
|
||||
afterCmd?: string // 后置命令
|
||||
}
|
||||
|
||||
// 部署本地节点配置
|
||||
export interface DeployLocalConfig extends DeploySSHConfig {}
|
||||
|
||||
// 部署节点配置(宝塔面板)
|
||||
export interface DeployBTPanelConfig {
|
||||
siteName: string
|
||||
@@ -268,7 +272,7 @@ export interface DeployStorageConfig {
|
||||
|
||||
// 部署节点配置
|
||||
export type DeployNodeConfig = DeployConfig<
|
||||
DeploySSHConfig | DeployBTPanelConfig | Deploy1PanelConfig | DeployCDNConfig | DeployStorageConfig
|
||||
DeploySSHConfig | DeployLocalConfig | DeployBTPanelConfig | Deploy1PanelConfig | DeployCDNConfig | DeployStorageConfig
|
||||
>
|
||||
|
||||
// 部署节点输入配置
|
||||
|
||||
@@ -4,12 +4,15 @@ import SvgIcon from '../svgIcon/index' // 注意修改引入路径以匹配实
|
||||
|
||||
// 定义支持的访问类型
|
||||
const types = {
|
||||
localhost: '本机部署',
|
||||
ssh: 'SSH',
|
||||
aliyun: '阿里云',
|
||||
tencentcloud: '腾讯云',
|
||||
btpanel: '宝塔面板',
|
||||
'1panel': '1Panel',
|
||||
huaweicloud: '华为云',
|
||||
baidu: '百度云',
|
||||
btpanel: '宝塔面板',
|
||||
btwaf: '宝塔WAF',
|
||||
'1panel': '1Panel',
|
||||
cloudflare: 'Cloudflare',
|
||||
mail: '邮件',
|
||||
dingtalk: '钉钉',
|
||||
@@ -56,10 +59,12 @@ export const AuthApiTypeIcon = defineComponent({
|
||||
|
||||
// 所有支持的类型直接映射到对应的资源名称
|
||||
const iconMap: Record<string, string> = {
|
||||
localhost: 'ssh',
|
||||
ssh: 'ssh',
|
||||
aliyun: 'aliyun',
|
||||
tencentcloud: 'tencentcloud',
|
||||
btpanel: 'btpanel',
|
||||
btwaf: 'btpanel',
|
||||
'1panel': '1panel',
|
||||
huaweicloud: 'huaweicloud',
|
||||
cloudflare: 'cloudflare',
|
||||
@@ -74,6 +79,7 @@ export const AuthApiTypeIcon = defineComponent({
|
||||
'aliyun-oss': 'aliyun',
|
||||
'1panel-site': '1panel',
|
||||
'btpanel-site': 'btpanel',
|
||||
baidu: 'baidu',
|
||||
}
|
||||
|
||||
// 返回匹配的图标路径或默认图标
|
||||
|
||||
Reference in New Issue
Block a user