【新增】部署类型七牛云oss、七牛云cdn、百度cdn、腾讯waf、腾讯edgeone、阿里云waf

【新增】解析类型godaddy
【新增】自定义CA授权管理
【调整】优化部署流程,减少代码冗余,提升类型添加效率
This commit is contained in:
chudong
2025-05-23 16:58:34 +08:00
parent 71de397e11
commit e5634d4992
263 changed files with 18348 additions and 14253 deletions

View File

@@ -0,0 +1,150 @@
import { defineComponent, PropType, VNode } from 'vue'
import { NButton, NFormItemGi, NGrid, NSelect, NText, NSpin, NFlex } from 'naive-ui'
// 类型导入
import type { CAProviderSelectProps, CAProviderOption, CAProviderSelectEmits } from './types'
// 绝对内部导入 - Controller
import { useCAProviderSelectController } from './useController'
// 绝对内部导入 - Components
import SvgIcon from '@components/SvgIcon'
// 绝对内部导入 - Utilities
import { $t } from '@locales/index'
/**
* @component CAProviderSelect
* @description CA授权选择组件支持选择Let's Encrypt和其他CA授权并提供跳转到CA授权管理页面的功能。
* 遵循 MVC/MV* 模式,将业务逻辑、状态管理与视图渲染分离。
*
* @example 基础使用
* <CAProviderSelect
* path="form.eabId"
* v-model:value="formValue.eabId"
* v-model:ca="formValue.ca"
* />
*
* @property {string} path - 表单路径,用于表单校验。
* @property {string} value - 当前选中的值 (通过 v-model:value 绑定)。
* @property {string} ca - 当前选中的CA类型 (通过 v-model:ca 绑定)。
* @property {boolean} [disabled=false] - 是否禁用。
* @property {string} [customClass] - 自定义CSS类名。
*
* @emits update:value - (value: { value: string; ca: string }) 当选择的CA授权变更时触发传递值和CA类型。
*/
export default defineComponent<CAProviderSelectProps>({
name: 'CAProviderSelect',
props: {
path: {
type: String,
required: true,
},
value: {
type: String,
required: true,
default: '',
},
ca: {
type: String,
required: true,
},
disabled: {
type: Boolean,
default: false,
},
customClass: {
type: String,
default: '',
},
},
emits: {
'update:value': (value: { value: string; ca: string }) => true,
},
setup(props: CAProviderSelectProps, { emit }: { emit: CAProviderSelectEmits }) {
const {
isLoading,
caProviderRef,
param,
handleUpdateValue,
handleFilter,
goToAddCAProvider,
errorMessage,
loadCAProviders,
} = useCAProviderSelectController(props, emit)
/**
* 渲染标签
* @param option - 选项
* @returns 渲染后的VNode
*/
const renderLabel = (option: CAProviderOption): VNode => {
return (
<NFlex align="center">
<SvgIcon icon={`cert-${option.ca}`} size="2rem" />
<NText>{option.label}</NText>
</NFlex>
)
}
/**
* 渲染单选标签
* @param option - 选项 (Record<string, any> 来自 naive-ui 的类型)
* @returns 渲染后的VNode
*/
const renderSingleSelectTag = ({ option }: { option: CAProviderOption }): VNode => {
return (
<div class="flex items-center">
{option.label ? renderLabel(option) : <NText class="text-[#aaa]">{$t('t_0_1747990228780')}</NText>}
</div>
)
}
return () => (
<NSpin show={isLoading.value}>
<NGrid cols={24} class={props.customClass}>
<NFormItemGi span={13} label={$t('t_1_1747990228492')} path={props.path}>
<NSelect
class="flex-1 w-full"
options={caProviderRef.value}
renderLabel={renderLabel}
renderTag={({ option }: { option: any }) => renderSingleSelectTag({ option: option as CAProviderOption })}
filterable
filter={(pattern: string, option: any) => handleFilter(pattern, option as CAProviderOption)}
placeholder={$t('t_0_1747990228780')}
value={param.value.value} // 使用 controller 中的 param.value.value
onUpdateValue={handleUpdateValue}
disabled={props.disabled}
v-slots={{
header: () => {
return (
<div
class="flex items-center cursor-pointer hover:text-[#333] hover:bg-[#eee]"
onClick={goToAddCAProvider}
>
{$t('t_0_1747990626044')}
</div>
)
},
empty: () => {
return <span class="text-[1.4rem]">{errorMessage.value || $t('t_2_1747990228008')}</span>
},
}}
/>
</NFormItemGi>
<NFormItemGi span={11}>
<NButton class="mx-[8px]" onClick={goToAddCAProvider} disabled={props.disabled}>
{$t('t_0_1747903670020')}
</NButton>
<NButton
class="mx-[8px]"
onClick={() => loadCAProviders()}
loading={isLoading.value}
disabled={props.disabled}
>
{$t('t_0_1746497662220')}
</NButton>
</NFormItemGi>
</NGrid>
</NSpin>
)
},
})

View File

@@ -0,0 +1,65 @@
/**
* @interface CAProviderOption
* @description CA授权选项的结构
*/
export interface CAProviderOption {
label: string
value: string
ca: string
}
/**
* @interface CAProviderSelectProps
* @description CAProviderSelect 组件的 Props 定义
*/
export interface CAProviderSelectProps {
/**
* @property path
* @description 表单路径,用于 naive-ui 表单校验
*/
path: string
/**
* @property value
* @description 当前选中的值
*/
value: string
/**
* @property ca
* @description 当前选中的CA类型
*/
ca: string
/**
* @property disabled
* @description 是否禁用选择器
* @default false
*/
disabled?: boolean
/**
* @property customClass
* @description 自定义CSS类名应用于 NGrid 组件
*/
customClass?: string
}
/**
* @interface CAProviderSelectEmits
* @description CAProviderSelect 组件的 Emits 定义
*/
export interface CAProviderSelectEmits {
(e: 'update:value', value: { value: string; ca: string }): void
}
/**
* @interface CAProviderControllerExposes
* @description useCAProviderSelectController 返回对象的类型接口
*/
export interface CAProviderControllerExposes {
param: import('vue').Ref<CAProviderOption>
caProviderRef: import('vue').Ref<CAProviderOption[]>
isLoading: import('vue').Ref<boolean>
errorMessage: import('vue').Ref<string>
goToAddCAProvider: () => void
handleUpdateValue: (value: string) => void
loadCAProviders: () => Promise<void>
handleFilter: (pattern: string, option: CAProviderOption) => boolean
}

View File

@@ -0,0 +1,148 @@
import { ref, watch, onMounted } from 'vue'
import type { CAProviderSelectProps, CAProviderOption, CAProviderSelectEmits } from './types'
// 绝对内部导入 - API
import { getAllEabList } from '@api/access'
// 绝对内部导入 - Hooks
import { useError } from '@baota/hooks/error'
// 绝对内部导入 - Utilities
import { $t } from '@locales/index'
/**
* @function useCAProviderSelectController
* @description CAProviderSelect 组件的控制器逻辑
* @param props - 组件的 props
* @param emit - 组件的 emit 函数
* @returns {CAProviderControllerExposes} 控制器暴露给视图的数据和方法
*/
export function useCAProviderSelectController(props: CAProviderSelectProps, emit: CAProviderSelectEmits) {
const { handleError } = useError()
const param = ref<CAProviderOption>({
label: '',
value: '',
ca: '',
})
const caProviderRef = ref<CAProviderOption[]>([])
const isLoading = ref(false)
const errorMessage = ref('')
/**
* @function goToAddCAProvider
* @description 跳转到CA授权管理页面
*/
const goToAddCAProvider = () => {
window.open('http://localhost:5173/auto-deploy', '_blank')
}
/**
* @function handleUpdateType
* @description 根据当前 param.value 更新 param 对象的 label 和 ca并 emit 更新事件
*/
const handleUpdateType = () => {
const selectedProvider = caProviderRef.value.find((item) => item.value === param.value.value)
if (selectedProvider) {
param.value = {
label: selectedProvider.label,
value: selectedProvider.value,
ca: selectedProvider.ca,
}
} else if (caProviderRef.value.length > 0 && param.value.value === '') {
// 如果 param.value 为空(例如初始状态或清空后),且 caProviderRef 列表不为空,则默认选中第一个
param.value = {
label: caProviderRef.value[0]?.label || '',
value: caProviderRef.value[0]?.value || '',
ca: caProviderRef.value[0]?.ca || '',
}
}
emit('update:value', { value: param.value.value, ca: param.value.ca })
}
/**
* @function handleUpdateValue
* @description 更新 param.value 并触发类型更新
* @param value - 新的选中值
*/
const handleUpdateValue = (value: string) => {
param.value.value = value
handleUpdateType()
}
/**
* @function loadCAProviders
* @description 加载CA授权选项
*/
const loadCAProviders = async () => {
isLoading.value = true
errorMessage.value = ''
try {
// 添加Let's Encrypt作为首选项
const letsEncryptOption: CAProviderOption = {
label: "Let's Encrypt",
value: '',
ca: 'letsencrypt',
}
// 获取其他CA授权列表
const { data } = await getAllEabList({ ca: '' }).fetch()
const eabOptions: CAProviderOption[] = (data || []).map((item) => ({
label: item.name,
value: item.id.toString(),
ca: item.ca,
}))
// 合并选项Let's Encrypt在首位
caProviderRef.value = [letsEncryptOption, ...eabOptions]
// 数据加载后,如果 props.value 有值,尝试根据 props.value 初始化 param
if (props.value) {
handleUpdateValue(props.value)
} else {
handleUpdateType() // 确保在 caProviderRef 更新后param 也得到相应更新
}
} catch (error) {
errorMessage.value = typeof error === 'string' ? error : $t('t_3_1747990229599')
handleError(error)
} finally {
isLoading.value = false
}
}
/**
* @function handleFilter
* @description NSelect 组件的搜索过滤函数
* @param pattern - 搜索文本
* @param option - 当前选项
* @returns {boolean} 是否匹配
*/
const handleFilter = (pattern: string, option: CAProviderOption): boolean => {
return option.label.toLowerCase().includes(pattern.toLowerCase())
}
watch(
() => props.value,
(newValue) => {
// 仅当外部 props.value 与内部 param.value.value 不一致时才更新
if (newValue !== param.value.value) {
handleUpdateValue(newValue)
}
},
{ immediate: true },
)
onMounted(() => {
loadCAProviders()
})
return {
param,
caProviderRef,
isLoading,
errorMessage,
goToAddCAProvider,
handleUpdateValue,
loadCAProviders,
handleFilter,
}
}