mirror of
https://gitee.com/mirrors/AllinSSL.git
synced 2026-03-10 00:31:10 +08:00
【调整】SSH地址支持域名形式
【新增】支持自定义监控端口 【新增】通知类型-企业微信 【新增】申请证书(Buypass)、自定义ACME服务器地址 【新增】授权API管理(namesilo、Bunny、Gcore、name.com、京东云)
This commit is contained in:
@@ -1,20 +1,65 @@
|
||||
import { NCard, NSpace, NDescriptions, NDescriptionsItem, NIcon, NButton } from 'naive-ui'
|
||||
import { NCard, NSpace, NDescriptions, NDescriptionsItem, NIcon, NButton, NBadge, NAlert } from 'naive-ui'
|
||||
import { $t } from '@locales/index'
|
||||
import { LogoGithub } from '@vicons/ionicons5'
|
||||
import { getVersion } from '@api/setting'
|
||||
import type { VersionData } from '@/types/setting'
|
||||
/**
|
||||
* 关于我们标签页组件
|
||||
*/
|
||||
export default defineComponent({
|
||||
name: 'AboutSettings',
|
||||
setup() {
|
||||
// 版本检查相关状态
|
||||
const versionData = ref<VersionData | null>(null)
|
||||
const hasUpdate = ref(false)
|
||||
|
||||
// 版本检查API
|
||||
const versionApi = getVersion()
|
||||
|
||||
// 检查版本更新
|
||||
const checkVersion = async () => {
|
||||
try {
|
||||
await versionApi.fetch()
|
||||
if (versionApi.data.value && versionApi.data.value.data) {
|
||||
const data = versionApi.data.value.data
|
||||
versionData.value = data
|
||||
hasUpdate.value = data.update === '1'
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('检查版本更新失败:', error)
|
||||
}
|
||||
}
|
||||
|
||||
// 跳转到GitHub
|
||||
const goToGitHub = () => {
|
||||
window.open('https://github.com/allinssl/allinssl', '_blank')
|
||||
}
|
||||
|
||||
// 组件挂载时检查版本
|
||||
onMounted(() => {
|
||||
checkVersion()
|
||||
})
|
||||
|
||||
return () => (
|
||||
<div class="about-settings">
|
||||
<NCard title={$t('t_4_1745833932780')} class="mb-4">
|
||||
<NSpace vertical size={24}>
|
||||
<NDescriptions bordered>
|
||||
<NDescriptionsItem label={$t('t_5_1745833933241')}>
|
||||
<div class="flex items-center">
|
||||
<span class="text-[2rem] font-medium">v1.0.4</span>
|
||||
<div class="flex items-center space-x-[1.2rem]">
|
||||
<span class="text-[2.0rem] font-medium">v1.0.4</span>
|
||||
{hasUpdate.value && versionData.value && (
|
||||
<div class="relative">
|
||||
<NBadge value="NEW" type="success" offset={[4, -3]}>
|
||||
<span
|
||||
class="text-[1.4rem] text-primary cursor-pointer font-medium inline-block px-[.8rem] py-[.4rem]"
|
||||
onClick={goToGitHub}
|
||||
>
|
||||
{versionData.value.new_version} 可用
|
||||
</span>
|
||||
</NBadge>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
</NDescriptionsItem>
|
||||
<NDescriptionsItem label={$t('t_29_1746667589773')}>
|
||||
@@ -22,7 +67,7 @@ export default defineComponent({
|
||||
<NIcon size="20" class="text-gray-600">
|
||||
<LogoGithub />
|
||||
</NIcon>
|
||||
<NButton text tag="a" href="https://github.com/allinssl/allinssl" target="_blank" type="primary">
|
||||
<NButton text onClick={goToGitHub} type="primary">
|
||||
https://github.com/allinssl/allinssl
|
||||
</NButton>
|
||||
</div>
|
||||
@@ -31,6 +76,33 @@ export default defineComponent({
|
||||
</NSpace>
|
||||
</NCard>
|
||||
|
||||
{/* 新版本信息卡片 */}
|
||||
{hasUpdate.value && versionData.value && (
|
||||
<NCard title="发现新版本" class="mb-4">
|
||||
<NAlert type="info" title={`新版本 ${versionData.value.new_version} 已发布`} class="mb-[1.6rem]">
|
||||
<div class="text-[1.4rem]">
|
||||
<div class="mb-[1.2rem] text-[1.4rem]">发布日期: {versionData.value.date}</div>
|
||||
<div class="mb-[1.2rem] text-[1.4rem]">
|
||||
<strong>更新内容:</strong>
|
||||
</div>
|
||||
<div class="whitespace-pre-line text-gray-700 text-[1.3rem] leading-relaxed">
|
||||
{versionData.value.log.replace(/\\r\\n/g, '\n').replace(/\\n/g, '\n')}
|
||||
</div>
|
||||
<div class="mt-4">
|
||||
<NButton size="medium" type="primary" onClick={goToGitHub}>
|
||||
<div class="flex items-center">
|
||||
<NIcon size="18" class="mr-2">
|
||||
<LogoGithub />
|
||||
</NIcon>
|
||||
前往GitHub下载
|
||||
</div>
|
||||
</NButton>
|
||||
</div>
|
||||
</div>
|
||||
</NAlert>
|
||||
</NCard>
|
||||
)}
|
||||
|
||||
<NCard title={$t('t_13_1745833933630')} class="mb-4">
|
||||
<div class="about-content">
|
||||
<p class="text-gray-700 leading-relaxed">
|
||||
|
||||
@@ -65,6 +65,19 @@ export default defineComponent({
|
||||
return () => (
|
||||
<div class="webhook-channel-form">
|
||||
<WebhookForm labelPlacement="top"></WebhookForm>
|
||||
|
||||
{/* 模板变量说明 */}
|
||||
<div class="mt-4 p-4 bg-gray-50 rounded-md">
|
||||
<div class="font-medium text-gray-700 mb-3 text-xl">模板变量将在发送时替换成实际值:</div>
|
||||
<div class="text-gray-600 space-y-3 text-lg">
|
||||
<div>
|
||||
<code class="px-2 py-1 bg-gray-200 rounded text-lg font-mono">__subject__</code>:通知主题
|
||||
</div>
|
||||
<div>
|
||||
<code class="px-2 py-1 bg-gray-200 rounded text-lg font-mono">__body__</code>:通知内容
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
},
|
||||
|
||||
@@ -0,0 +1,94 @@
|
||||
import { useForm, useModalHooks } from '@baota/naive-ui/hooks'
|
||||
import { useError } from '@baota/hooks/error'
|
||||
import { useWecomChannelFormController } from './useController'
|
||||
import { useStore } from '@settings/useStore'
|
||||
|
||||
import type { ReportWecom, ReportType } from '@/types/setting'
|
||||
|
||||
/**
|
||||
* 企业微信通知渠道表单组件
|
||||
*/
|
||||
export default defineComponent({
|
||||
name: 'WecomChannelModel',
|
||||
props: {
|
||||
data: {
|
||||
type: Object as PropType<ReportType<ReportWecom> | null>,
|
||||
default: () => null,
|
||||
},
|
||||
},
|
||||
setup(props: { data: ReportType<ReportWecom> | null }) {
|
||||
const { handleError } = useError()
|
||||
const { confirm } = useModalHooks()
|
||||
const { fetchNotifyChannels } = useStore()
|
||||
const { config, rules, wecomChannelForm, submitForm } = useWecomChannelFormController()
|
||||
|
||||
if (props.data) {
|
||||
const { name, config } = props.data
|
||||
wecomChannelForm.value = {
|
||||
name,
|
||||
...config,
|
||||
}
|
||||
}
|
||||
// 使用表单hooks
|
||||
const {
|
||||
component: WecomForm,
|
||||
example,
|
||||
data,
|
||||
} = useForm({
|
||||
config,
|
||||
defaultValue: wecomChannelForm,
|
||||
rules,
|
||||
})
|
||||
|
||||
// 关联确认按钮
|
||||
confirm(async (close) => {
|
||||
try {
|
||||
const { name, ...other } = data.value
|
||||
await example.value?.validate()
|
||||
const res = await submitForm(
|
||||
{
|
||||
type: 'workwx',
|
||||
name: name || '',
|
||||
config: other,
|
||||
},
|
||||
example,
|
||||
props.data?.id,
|
||||
)
|
||||
|
||||
fetchNotifyChannels()
|
||||
if (res) close()
|
||||
} catch (error) {
|
||||
handleError(error)
|
||||
}
|
||||
})
|
||||
|
||||
return () => (
|
||||
<div class="wecom-channel-form">
|
||||
<WecomForm labelPlacement="top"></WecomForm>
|
||||
|
||||
{/* 模板变量说明 */}
|
||||
<div class="mt-4 p-4 bg-gray-50 rounded-md">
|
||||
<div class="font-medium text-gray-700 mb-3 text-xl">模板变量将在发送时替换成实际值:</div>
|
||||
<div class="text-gray-600 space-y-3 text-lg">
|
||||
<div>
|
||||
<code class="px-2 py-1 bg-gray-200 rounded text-lg font-mono">__subject__</code>:通知主题
|
||||
</div>
|
||||
<div>
|
||||
<code class="px-2 py-1 bg-gray-200 rounded text-lg font-mono">__body__</code>:通知内容
|
||||
</div>
|
||||
</div>
|
||||
<div class="mt-4 pt-3 border-t border-gray-200">
|
||||
<a
|
||||
href="https://developer.work.weixin.qq.com/document/path/91770"
|
||||
target="_blank"
|
||||
class="hover:opacity-80 text-xl"
|
||||
style="color: #20a50a"
|
||||
>
|
||||
📖 查看企业微信机器人消息格式教程
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
},
|
||||
})
|
||||
@@ -3,13 +3,21 @@ import { useFormHooks, useLoadingMask } from '@baota/naive-ui/hooks'
|
||||
import { useError } from '@baota/hooks/error'
|
||||
import { $t } from '@locales/index'
|
||||
import { useStore } from '@settings/useStore'
|
||||
import type { ReportMail, ReportFeishu, ReportWebhook, ReportDingtalk, AddReportParams } from '@/types/setting'
|
||||
import type {
|
||||
ReportMail,
|
||||
ReportFeishu,
|
||||
ReportWebhook,
|
||||
ReportDingtalk,
|
||||
ReportWecom,
|
||||
AddReportParams,
|
||||
} from '@/types/setting'
|
||||
|
||||
const {
|
||||
emailChannelForm,
|
||||
feishuChannelForm,
|
||||
webhookChannelForm,
|
||||
dingtalkChannelForm,
|
||||
wecomChannelForm,
|
||||
addReportChannel,
|
||||
updateReportChannel,
|
||||
} = useStore()
|
||||
@@ -359,3 +367,100 @@ export const useDingtalkChannelFormController = () => {
|
||||
submitForm,
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 企业微信通知渠道表单控制器
|
||||
* @function useWecomChannelFormController
|
||||
* @description 提供企业微信通知渠道表单的配置、规则和提交方法
|
||||
* @returns {object} 返回表单相关配置、规则和方法
|
||||
*/
|
||||
export const useWecomChannelFormController = () => {
|
||||
const { open: openLoad, close: closeLoad } = useLoadingMask({ text: $t('t_0_1746667592819') })
|
||||
/**
|
||||
* 表单验证规则
|
||||
* @type {FormRules}
|
||||
*/
|
||||
const rules: FormRules = {
|
||||
name: {
|
||||
required: true,
|
||||
trigger: ['input', 'blur'],
|
||||
message: $t('t_25_1746773349596'),
|
||||
},
|
||||
url: {
|
||||
required: true,
|
||||
trigger: ['input', 'blur'],
|
||||
message: '请输入企业微信webhook地址',
|
||||
},
|
||||
}
|
||||
|
||||
/**
|
||||
* 表单配置
|
||||
* @type {ComputedRef<FormConfig>}
|
||||
* @description 生成企业微信通知渠道表单的字段配置
|
||||
*/
|
||||
const config = computed(() => [
|
||||
useFormInput($t('t_2_1745289353944'), 'name'),
|
||||
useFormInput('企业微信WebHook地址', 'url'),
|
||||
useFormTextarea(
|
||||
'推送数据格式',
|
||||
'data',
|
||||
{
|
||||
placeholder: `请输入企业微信推送数据格式,支持模板变量 __subject__ 和 __body__
|
||||
|
||||
示例格式:
|
||||
{
|
||||
"msgtype": "news",
|
||||
"news": {
|
||||
"articles": [
|
||||
{
|
||||
"title": "__subject__",
|
||||
"description": "__body__。",
|
||||
"url": "https://allinssl.com/",
|
||||
"picurl": "https://allinssl.com/logo.svg"
|
||||
}
|
||||
]
|
||||
}
|
||||
}`,
|
||||
rows: 12,
|
||||
},
|
||||
{ showRequireMark: false },
|
||||
),
|
||||
])
|
||||
|
||||
/**
|
||||
* 提交表单
|
||||
* @async
|
||||
* @function submitForm
|
||||
* @description 验证并提交企业微信通知渠道表单
|
||||
* @param {any} params - 表单参数
|
||||
* @param {Ref<FormInst>} formRef - 表单实例引用
|
||||
* @returns {Promise<boolean>} 提交成功返回true,失败返回false
|
||||
*/
|
||||
const submitForm = async (
|
||||
{ config, ...other }: AddReportParams<ReportWecom>,
|
||||
formRef: Ref<FormInst | null>,
|
||||
id?: number,
|
||||
) => {
|
||||
try {
|
||||
openLoad()
|
||||
if (id) {
|
||||
await updateReportChannel({ id, config: JSON.stringify(config), ...other })
|
||||
} else {
|
||||
await addReportChannel({ config: JSON.stringify(config), ...other })
|
||||
}
|
||||
return true
|
||||
} catch (error) {
|
||||
handleError(error)
|
||||
return false
|
||||
} finally {
|
||||
closeLoad()
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
config,
|
||||
rules,
|
||||
wecomChannelForm,
|
||||
submitForm,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -16,6 +16,7 @@ export default defineComponent({
|
||||
openAddFeishuChannelModal,
|
||||
openAddWebhookChannelModal,
|
||||
openAddDingtalkChannelModal,
|
||||
openAddWecomChannelModal,
|
||||
editChannelConfig,
|
||||
testChannelConfig,
|
||||
confirmDeleteChannel,
|
||||
@@ -64,6 +65,12 @@ export default defineComponent({
|
||||
{$t('t_1_1746676859550')}
|
||||
</NButton>
|
||||
)
|
||||
} else if (type === 'workwx') {
|
||||
return (
|
||||
<NButton strong secondary type="primary" onClick={() => openAddWecomChannelModal(getConfiguredCount(type))}>
|
||||
{$t('t_1_1746676859550')}
|
||||
</NButton>
|
||||
)
|
||||
}
|
||||
// 其他渠道暂未支持
|
||||
return (
|
||||
@@ -100,7 +107,7 @@ export default defineComponent({
|
||||
color: '#1677ff',
|
||||
},
|
||||
{
|
||||
type: 'wecom',
|
||||
type: 'workwx',
|
||||
name: $t('t_7_1746676857191'),
|
||||
description: $t('t_8_1746676860457'),
|
||||
color: '#07c160',
|
||||
|
||||
@@ -10,6 +10,7 @@ import EmailChannelModel from './components/channel/EmailChannelModel'
|
||||
import FeishuChannelModel from './components/channel/FeishuChannelModel'
|
||||
import WebhookChannelModel from './components/channel/WebhookChannelModel'
|
||||
import DingtalkChannelModel from './components/channel/DingtalkChannelModel'
|
||||
import WecomChannelModel from './components/channel/WecomChannelModel'
|
||||
import type { ReportMail, SaveSettingParams, ReportType } from '@/types/setting'
|
||||
|
||||
const {
|
||||
@@ -178,6 +179,25 @@ export const useController = () => {
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* 打开添加企业微信通知渠道弹窗
|
||||
* @function openAddWecomChannelModal
|
||||
* @description 打开添加企业微信通知渠道的模态框,并在关闭后刷新通知渠道列表
|
||||
* @returns {void} 无返回值
|
||||
*/
|
||||
const openAddWecomChannelModal = (limit: number = 1) => {
|
||||
if (limit >= 1) {
|
||||
message.warning('企业微信通知渠道已达到上限')
|
||||
return
|
||||
}
|
||||
useModal({
|
||||
title: '添加企业微信通知',
|
||||
area: 650,
|
||||
component: WecomChannelModel,
|
||||
footer: true,
|
||||
})
|
||||
}
|
||||
|
||||
// 处理启用状态切换
|
||||
const handleEnableChange = async (item: ReportType<ReportMail>) => {
|
||||
useDialog({
|
||||
@@ -263,6 +283,17 @@ export const useController = () => {
|
||||
footer: true,
|
||||
onClose: () => fetchNotifyChannels(),
|
||||
})
|
||||
} else if (item.type === 'workwx') {
|
||||
useModal({
|
||||
title: '编辑企业微信通知',
|
||||
area: 650,
|
||||
component: WecomChannelModel,
|
||||
componentProps: {
|
||||
data: item,
|
||||
},
|
||||
footer: true,
|
||||
onClose: () => fetchNotifyChannels(),
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
@@ -274,7 +305,13 @@ export const useController = () => {
|
||||
* @returns {void} 无返回值
|
||||
*/
|
||||
const testChannelConfig = (item: ReportType<any>) => {
|
||||
if (item.type !== 'mail' && item.type !== 'feishu' && item.type !== 'webhook' && item.type !== 'dingtalk') {
|
||||
if (
|
||||
item.type !== 'mail' &&
|
||||
item.type !== 'feishu' &&
|
||||
item.type !== 'webhook' &&
|
||||
item.type !== 'dingtalk' &&
|
||||
item.type !== 'workwx'
|
||||
) {
|
||||
message.warning($t('t_19_1746773352558'))
|
||||
return
|
||||
}
|
||||
@@ -283,6 +320,7 @@ export const useController = () => {
|
||||
feishu: $t('t_34_1746773350153'),
|
||||
webhook: $t('t_3_1748591484673'),
|
||||
dingtalk: $t('t_32_1746773348993'),
|
||||
workwx: $t('t_33_1746773350932'),
|
||||
}
|
||||
const { open, close } = useLoadingMask({ text: $t('t_4_1748591492587', { type: typeMap[item.type] }) })
|
||||
useDialog({
|
||||
@@ -337,6 +375,7 @@ export const useController = () => {
|
||||
openAddFeishuChannelModal,
|
||||
openAddWebhookChannelModal,
|
||||
openAddDingtalkChannelModal,
|
||||
openAddWecomChannelModal,
|
||||
handleEnableChange,
|
||||
editChannelConfig,
|
||||
testChannelConfig,
|
||||
|
||||
@@ -22,6 +22,7 @@ import type {
|
||||
ReportFeishu,
|
||||
ReportWebhook,
|
||||
ReportDingtalk,
|
||||
ReportWecom,
|
||||
} from '@/types/setting'
|
||||
|
||||
const { handleError } = useError()
|
||||
@@ -63,7 +64,7 @@ export const useSettingsStore = defineStore('settings-store', () => {
|
||||
const channelTypes = ref<Record<string, string>>({
|
||||
mail: $t('t_68_1745289354676'),
|
||||
dingtalk: $t('t_32_1746773348993'),
|
||||
wecom: $t('t_33_1746773350932'),
|
||||
workwx: $t('t_33_1746773350932'),
|
||||
feishu: $t('t_34_1746773350153'),
|
||||
webhook: 'WebHook',
|
||||
})
|
||||
@@ -107,6 +108,26 @@ export const useSettingsStore = defineStore('settings-store', () => {
|
||||
secret: '', // 钉钉webhook加密密钥(可选)
|
||||
})
|
||||
|
||||
// 企业微信通知渠道表单
|
||||
const wecomChannelForm = ref<ReportWecom>({
|
||||
name: '',
|
||||
enabled: '1',
|
||||
url: '', // 企业微信webhook地址
|
||||
data: `{
|
||||
"msgtype": "news",
|
||||
"news": {
|
||||
"articles": [
|
||||
{
|
||||
"title": "__subject__",
|
||||
"description": "__body__。",
|
||||
"url": "https://allinssl.com/",
|
||||
"picurl": "https://allinssl.com/logo.svg"
|
||||
}
|
||||
]
|
||||
}
|
||||
}`, // 企业微信推送数据格式
|
||||
})
|
||||
|
||||
// 关于页面数据
|
||||
const aboutInfo = ref({
|
||||
version: '1.0.0',
|
||||
@@ -250,6 +271,7 @@ export const useSettingsStore = defineStore('settings-store', () => {
|
||||
feishuChannelForm,
|
||||
webhookChannelForm,
|
||||
dingtalkChannelForm,
|
||||
wecomChannelForm,
|
||||
aboutInfo,
|
||||
|
||||
// 方法
|
||||
|
||||
Reference in New Issue
Block a user