mirror of
https://gitee.com/mirrors/AllinSSL.git
synced 2026-03-09 16:21:10 +08:00
【调整】SSH地址支持域名形式
【新增】支持自定义监控端口 【新增】通知类型-企业微信 【新增】申请证书(Buypass)、自定义ACME服务器地址 【新增】授权API管理(namesilo、Bunny、Gcore、name.com、京东云)
This commit is contained in:
@@ -114,9 +114,11 @@ export default defineComponent<CAProviderSelectProps>({
|
||||
class="flex-1 w-full"
|
||||
options={caProviderRef.value}
|
||||
renderLabel={renderLabel}
|
||||
renderTag={({ option }: { option: any }) => renderSingleSelectTag({ option: option as CAProviderOption })}
|
||||
renderTag={({ option }: { option: unknown }) =>
|
||||
renderSingleSelectTag({ option: option as CAProviderOption })
|
||||
}
|
||||
filterable
|
||||
filter={(pattern: string, option: any) => handleFilter(pattern, option as CAProviderOption)}
|
||||
filter={(pattern: string, option: unknown) => handleFilter(pattern, option as CAProviderOption)}
|
||||
placeholder={$t('t_0_1747990228780')}
|
||||
value={param.value.value} // 使用 controller 中的 param.value.value
|
||||
onUpdateValue={handleUpdateValue}
|
||||
|
||||
@@ -31,7 +31,7 @@ export interface CAProviderSelectProps {
|
||||
ca: string
|
||||
/**
|
||||
* @property email
|
||||
* @description 邮箱地址,当 value 不为空时会被赋值
|
||||
* @description 邮箱地址,编辑时从工作流content中传入,新建时为空
|
||||
*/
|
||||
email: string
|
||||
/**
|
||||
|
||||
@@ -44,26 +44,36 @@ export function useCAProviderSelectController(props: CAProviderSelectProps, emit
|
||||
const selectedProvider = caProviderRef.value.find((item) => item.value === param.value.value)
|
||||
|
||||
if (selectedProvider) {
|
||||
// 对于 Let's Encrypt 和 Buypass,使用传入的工作流邮件
|
||||
let email = selectedProvider.email
|
||||
if (selectedProvider.ca === 'letsencrypt' || selectedProvider.ca === 'buypass') {
|
||||
email = props.email || selectedProvider.email
|
||||
}
|
||||
|
||||
param.value = {
|
||||
label: selectedProvider.label,
|
||||
value: selectedProvider.value,
|
||||
ca: selectedProvider.ca,
|
||||
email: selectedProvider.email,
|
||||
email: email,
|
||||
}
|
||||
} else if (caProviderRef.value.length > 0 && param.value.value === '') {
|
||||
// 如果 param.value 为空(例如初始状态或清空后),且 caProviderRef 列表不为空,则默认选中第一个
|
||||
const firstProvider = caProviderRef.value[0]
|
||||
let email = firstProvider?.email || ''
|
||||
if (firstProvider && (firstProvider.ca === 'letsencrypt' || firstProvider.ca === 'buypass')) {
|
||||
email = props.email || firstProvider.email
|
||||
}
|
||||
|
||||
param.value = {
|
||||
label: caProviderRef.value[0]?.label || '',
|
||||
value: caProviderRef.value[0]?.value || '',
|
||||
ca: caProviderRef.value[0]?.ca || '',
|
||||
email: caProviderRef.value[0]?.email || '',
|
||||
label: firstProvider?.label || '',
|
||||
value: firstProvider?.value || '',
|
||||
ca: firstProvider?.ca || '',
|
||||
email: email,
|
||||
}
|
||||
}
|
||||
|
||||
// 当 value 不为空时,将其赋值给 email 字段
|
||||
if (param.value.value !== '') {
|
||||
emit('update:email', param.value.email)
|
||||
}
|
||||
// 始终触发邮件更新事件,确保邮件字段能正确渲染
|
||||
emit('update:email', param.value.email)
|
||||
|
||||
emit('update:value', { value: param.value.value, ca: param.value.ca, email: param.value.email })
|
||||
}
|
||||
@@ -86,15 +96,23 @@ export function useCAProviderSelectController(props: CAProviderSelectProps, emit
|
||||
isLoading.value = true
|
||||
errorMessage.value = ''
|
||||
try {
|
||||
// 添加Let's Encrypt作为首选项
|
||||
// 添加Let's Encrypt作为首选项,使用传入的工作流邮件
|
||||
const letsEncryptOption: CAProviderOption = {
|
||||
label: "Let's Encrypt",
|
||||
value: '',
|
||||
ca: 'letsencrypt',
|
||||
email: '',
|
||||
email: props.email || '',
|
||||
}
|
||||
|
||||
// 获取其他CA授权列表
|
||||
// 添加Buypass作为第二选项,使用传入的工作流邮件
|
||||
const buypassOption: CAProviderOption = {
|
||||
label: 'Buypass',
|
||||
value: 'buypass',
|
||||
ca: 'buypass',
|
||||
email: props.email || '',
|
||||
}
|
||||
|
||||
// 获取其他CA授权列表,使用接口返回的邮件
|
||||
const { data } = await getAllEabList({ ca: '' }).fetch()
|
||||
const eabOptions: CAProviderOption[] = (data || []).map((item) => ({
|
||||
label: item.name,
|
||||
@@ -103,8 +121,8 @@ export function useCAProviderSelectController(props: CAProviderSelectProps, emit
|
||||
email: item.mail,
|
||||
}))
|
||||
|
||||
// 合并选项,Let's Encrypt在首位
|
||||
caProviderRef.value = [letsEncryptOption, ...eabOptions]
|
||||
// 合并选项,Let's Encrypt在首位,Buypass在第二位
|
||||
caProviderRef.value = [letsEncryptOption, buypassOption, ...eabOptions]
|
||||
|
||||
// 数据加载后,如果 props.value 有值,尝试根据 props.value 初始化 param
|
||||
if (props.value) {
|
||||
|
||||
115
frontend/apps/allin-ssl/src/components/UpdateLogModal/index.tsx
Normal file
115
frontend/apps/allin-ssl/src/components/UpdateLogModal/index.tsx
Normal file
@@ -0,0 +1,115 @@
|
||||
// External Libraries
|
||||
import { defineComponent } from 'vue'
|
||||
import { NModal, NButton, NSpace, NScrollbar, NIcon } from 'naive-ui'
|
||||
import { LogoGithub } from '@vicons/ionicons5'
|
||||
|
||||
// Type Imports
|
||||
import type { PropType } from 'vue'
|
||||
import type { UpdateLogModalProps } from './types'
|
||||
import type { VersionData } from '@/types/setting'
|
||||
|
||||
// Relative Internal Imports - Controller
|
||||
import { useUpdateLogModalController } from './useController'
|
||||
|
||||
/**
|
||||
* @description 更新日志弹窗组件。显示版本更新信息和更新日志。
|
||||
* @example
|
||||
* <UpdateLogModal
|
||||
* v-model:show="showModal"
|
||||
* :versionData="versionData"
|
||||
* />
|
||||
*/
|
||||
export default defineComponent({
|
||||
name: 'UpdateLogModal',
|
||||
props: {
|
||||
/**
|
||||
* 是否显示弹窗
|
||||
* @default false
|
||||
*/
|
||||
show: {
|
||||
type: Boolean as PropType<UpdateLogModalProps['show']>,
|
||||
default: false,
|
||||
},
|
||||
/**
|
||||
* 版本数据
|
||||
* @default null
|
||||
*/
|
||||
versionData: {
|
||||
type: Object as PropType<VersionData | null>,
|
||||
default: null,
|
||||
},
|
||||
},
|
||||
/**
|
||||
* @event update:show - 当弹窗显示状态更新时触发
|
||||
* @param {boolean} show - 弹窗显示状态
|
||||
*/
|
||||
emits: {
|
||||
'update:show': (payload: boolean) => typeof payload === 'boolean',
|
||||
},
|
||||
setup(props: UpdateLogModalProps, { emit }) {
|
||||
const { formattedLog, goToGitHub, handleClose } = useUpdateLogModalController(props, emit)
|
||||
|
||||
return () => (
|
||||
<NModal
|
||||
show={props.show}
|
||||
onUpdateShow={(show: boolean) => emit('update:show', show)}
|
||||
preset="card"
|
||||
title="发现新版本"
|
||||
style={{ width: '600px', maxWidth: '90vw' }}
|
||||
maskClosable={false}
|
||||
closable={true}
|
||||
onClose={handleClose}
|
||||
>
|
||||
{props.versionData && (
|
||||
<div class="update-log-content">
|
||||
{/* 版本信息 */}
|
||||
<div class="mb-[1.6rem]">
|
||||
<div class="flex items-center justify-between mb-[.8rem]">
|
||||
<span class="text-[1.5rem] font-medium">当前版本: {props.versionData.version}</span>
|
||||
<span class="text-[1.5rem] font-medium text-primary">最新版本: {props.versionData.new_version}</span>
|
||||
</div>
|
||||
<div class="text-[1.4rem] text-gray-500">发布日期: {props.versionData.date}</div>
|
||||
</div>
|
||||
|
||||
{/* 更新日志 */}
|
||||
<div class="mb-[2.4rem]">
|
||||
<h3 class="text-[1.6rem] font-medium mb-[1.2rem]">更新日志</h3>
|
||||
<NScrollbar style={{ maxHeight: '300px' }}>
|
||||
<div class="update-log-list">
|
||||
{formattedLog.value.map((line, index) => (
|
||||
<div key={index} class="mb-[.8rem]">
|
||||
{line.startsWith('■') ? (
|
||||
<div class="text-[1.4rem] font-medium text-primary mb-[.4rem]">{line}</div>
|
||||
) : line.startsWith('新增:') || line.startsWith('调整:') ? (
|
||||
<div class="ml-[1.6rem] text-[1.3rem] text-green-600">{line}</div>
|
||||
) : (
|
||||
<div class="ml-[1.6rem] text-[1.3rem] text-gray-700">{line}</div>
|
||||
)}
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
</NScrollbar>
|
||||
</div>
|
||||
|
||||
{/* 操作按钮 */}
|
||||
<div class="flex justify-end">
|
||||
<NSpace size="medium">
|
||||
<NButton size="medium" onClick={handleClose}>
|
||||
<span class="text-[1.4rem]">稍后更新</span>
|
||||
</NButton>
|
||||
<NButton size="medium" type="primary" onClick={goToGitHub}>
|
||||
<div class="flex items-center">
|
||||
<NIcon size="18" class="mr-[.8rem]">
|
||||
<LogoGithub />
|
||||
</NIcon>
|
||||
<span class="text-[1.4rem]">前往GitHub下载</span>
|
||||
</div>
|
||||
</NButton>
|
||||
</NSpace>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
</NModal>
|
||||
)
|
||||
},
|
||||
})
|
||||
44
frontend/apps/allin-ssl/src/components/UpdateLogModal/types.d.ts
vendored
Normal file
44
frontend/apps/allin-ssl/src/components/UpdateLogModal/types.d.ts
vendored
Normal file
@@ -0,0 +1,44 @@
|
||||
// Type Imports
|
||||
import type { Ref } from 'vue'
|
||||
import type { VersionData } from '@/types/setting'
|
||||
|
||||
/**
|
||||
* @description 更新日志弹窗组件的 Props 定义
|
||||
*/
|
||||
export interface UpdateLogModalProps {
|
||||
/**
|
||||
* 是否显示弹窗
|
||||
* @default false
|
||||
*/
|
||||
show: boolean
|
||||
/**
|
||||
* 版本数据
|
||||
* @default null
|
||||
*/
|
||||
versionData: VersionData | null
|
||||
}
|
||||
|
||||
/**
|
||||
* @description 更新日志弹窗组件的 Emits 定义
|
||||
*/
|
||||
export interface UpdateLogModalEmits {
|
||||
(e: 'update:show', show: boolean): void
|
||||
}
|
||||
|
||||
/**
|
||||
* @description 更新日志弹窗控制器暴露给视图的数据和方法
|
||||
*/
|
||||
export interface UpdateLogModalControllerExposes {
|
||||
/**
|
||||
* 格式化后的更新日志行数组
|
||||
*/
|
||||
formattedLog: Ref<string[]>
|
||||
/**
|
||||
* 跳转到GitHub的方法
|
||||
*/
|
||||
goToGitHub: () => void
|
||||
/**
|
||||
* 关闭弹窗的方法
|
||||
*/
|
||||
handleClose: () => void
|
||||
}
|
||||
@@ -0,0 +1,50 @@
|
||||
// External Libraries
|
||||
import { computed } from 'vue'
|
||||
|
||||
// Type Imports
|
||||
import type { UpdateLogModalProps, UpdateLogModalEmits, UpdateLogModalControllerExposes } from './types'
|
||||
|
||||
/**
|
||||
* @description 更新日志弹窗组件的控制器逻辑
|
||||
* @param props - 组件的 props
|
||||
* @param emit - 组件的 emit 函数
|
||||
* @returns {UpdateLogModalControllerExposes} 暴露给视图的响应式数据和方法
|
||||
*/
|
||||
export function useUpdateLogModalController(
|
||||
props: UpdateLogModalProps,
|
||||
emit: (event: 'update:show', payload: boolean) => void,
|
||||
): UpdateLogModalControllerExposes {
|
||||
|
||||
/**
|
||||
* @description 处理更新日志文本,将 \r\n 和 \n 转换为换行
|
||||
*/
|
||||
const formattedLog = computed(() => {
|
||||
if (!props.versionData?.log) return []
|
||||
return props.versionData.log
|
||||
.replace(/\\r\\n/g, '\n')
|
||||
.replace(/\\n/g, '\n')
|
||||
.split('\n')
|
||||
.filter(line => line.trim() !== '')
|
||||
})
|
||||
|
||||
/**
|
||||
* @description 跳转到GitHub
|
||||
*/
|
||||
const goToGitHub = (): void => {
|
||||
window.open('https://github.com/allinssl/allinssl', '_blank')
|
||||
emit('update:show', false)
|
||||
}
|
||||
|
||||
/**
|
||||
* @description 关闭弹窗
|
||||
*/
|
||||
const handleClose = (): void => {
|
||||
emit('update:show', false)
|
||||
}
|
||||
|
||||
return {
|
||||
formattedLog,
|
||||
goToGitHub,
|
||||
handleClose,
|
||||
}
|
||||
}
|
||||
@@ -114,6 +114,9 @@ nodeOptions[APPLY] = () =>
|
||||
provider_id: '',
|
||||
algorithm: 'RSA2048',
|
||||
skip_check: 0,
|
||||
close_cname: 0,
|
||||
max_wait: undefined,
|
||||
ignore_check: 0,
|
||||
},
|
||||
childNode: null,
|
||||
},
|
||||
|
||||
@@ -217,6 +217,9 @@ export interface ApplyNodeConfig {
|
||||
name_server: string // DNS递归服务器
|
||||
skip_check: number // 跳过检查
|
||||
algorithm: string // 数字证书算法
|
||||
close_cname: number // 禁用CNAME支持,0关闭1开启,默认0
|
||||
max_wait?: number // 预检查超时时间,单位秒(可选)
|
||||
ignore_check: number // 忽略预检查结果,1继续,0停止,默认0
|
||||
// 高级功能
|
||||
// algorithm: 'RSA2048' | 'RSA3072' | 'RSA4096' | 'RSA8192' | 'EC256' | 'EC384' // 数字证书算法
|
||||
// dnsServer?: string // 指定DNS解析服务器
|
||||
|
||||
Reference in New Issue
Block a user