mirror of
https://gitee.com/mirrors/AllinSSL.git
synced 2026-03-08 07:41:10 +08:00
【调整】SSH地址支持域名形式
【新增】支持自定义监控端口 【新增】通知类型-企业微信 【新增】申请证书(Buypass)、自定义ACME服务器地址 【新增】授权API管理(namesilo、Bunny、Gcore、name.com、京东云)
This commit is contained in:
@@ -8,6 +8,8 @@ import type {
|
||||
GetReportListResponse,
|
||||
GetSettingParams,
|
||||
GetSettingResponse,
|
||||
GetVersionParams,
|
||||
GetVersionResponse,
|
||||
SaveSettingParams,
|
||||
TestReportParams,
|
||||
UpdateReportParams,
|
||||
@@ -69,5 +71,15 @@ export const testReport = (params?: TestReportParams): useAxiosReturn<AxiosRespo
|
||||
* @param {GetReportListParams} [params] 请求参数
|
||||
* @returns {useAxiosReturn<GetReportListResponse, GetReportListParams>} 获取告警类型列表的组合式 API 调用封装。包含响应数据、加载状态及执行函数。
|
||||
*/
|
||||
export const getReportList = (params?: GetReportListParams): useAxiosReturn<GetReportListResponse, GetReportListParams> =>
|
||||
export const getReportList = (
|
||||
params?: GetReportListParams,
|
||||
): useAxiosReturn<GetReportListResponse, GetReportListParams> =>
|
||||
useApi<GetReportListResponse, GetReportListParams>('/v1/report/get_list', params)
|
||||
|
||||
/**
|
||||
* @description 获取版本信息
|
||||
* @param {GetVersionParams} [params] 请求参数
|
||||
* @returns {useAxiosReturn<GetVersionResponse, GetVersionParams>} 获取版本信息的组合式 API 调用封装。包含响应数据、加载状态及执行函数。
|
||||
*/
|
||||
export const getVersion = (params?: GetVersionParams): useAxiosReturn<GetVersionResponse, GetVersionParams> =>
|
||||
useApi<GetVersionResponse, GetVersionParams>('/v1/setting/get_version', params)
|
||||
|
||||
@@ -6,6 +6,7 @@ import type {
|
||||
DeleteWorkflowParams,
|
||||
EnableWorkflowParams,
|
||||
ExecuteWorkflowParams,
|
||||
StopWorkflowParams,
|
||||
UpdateWorkflowExecTypeParams,
|
||||
UpdateWorkflowParams,
|
||||
WorkflowHistoryDetailParams,
|
||||
@@ -23,7 +24,9 @@ import { useApi } from '@api/index'
|
||||
* @param {WorkflowListParams} [params] 请求参数
|
||||
* @returns {useAxiosReturn<WorkflowListResponse, WorkflowListParams>} 获取工作流列表的组合式 API 调用封装。包含响应数据、加载状态及执行函数。
|
||||
*/
|
||||
export const getWorkflowList = (params?: WorkflowListParams): useAxiosReturn<WorkflowListResponse, WorkflowListParams> =>
|
||||
export const getWorkflowList = (
|
||||
params?: WorkflowListParams,
|
||||
): useAxiosReturn<WorkflowListResponse, WorkflowListParams> =>
|
||||
useApi<WorkflowListResponse, WorkflowListParams>('/v1/workflow/get_list', params)
|
||||
|
||||
/**
|
||||
@@ -39,7 +42,9 @@ export const addWorkflow = (params?: AddWorkflowParams): useAxiosReturn<AxiosRes
|
||||
* @param {UpdateWorkflowParams} [params] 请求参数
|
||||
* @returns {useAxiosReturn<AxiosResponseData, UpdateWorkflowParams>} 修改工作流的组合式 API 调用封装。包含响应数据、加载状态及执行函数。
|
||||
*/
|
||||
export const updateWorkflow = (params?: UpdateWorkflowParams): useAxiosReturn<AxiosResponseData, UpdateWorkflowParams> =>
|
||||
export const updateWorkflow = (
|
||||
params?: UpdateWorkflowParams,
|
||||
): useAxiosReturn<AxiosResponseData, UpdateWorkflowParams> =>
|
||||
useApi<AxiosResponseData, UpdateWorkflowParams>('/v1/workflow/upd_workflow', params)
|
||||
|
||||
/**
|
||||
@@ -47,7 +52,9 @@ export const updateWorkflow = (params?: UpdateWorkflowParams): useAxiosReturn<Ax
|
||||
* @param {DeleteWorkflowParams} [params] 请求参数
|
||||
* @returns {useAxiosReturn<AxiosResponseData, DeleteWorkflowParams>} 删除工作流的组合式 API 调用封装。包含响应数据、加载状态及执行函数。
|
||||
*/
|
||||
export const deleteWorkflow = (params?: DeleteWorkflowParams): useAxiosReturn<AxiosResponseData, DeleteWorkflowParams> =>
|
||||
export const deleteWorkflow = (
|
||||
params?: DeleteWorkflowParams,
|
||||
): useAxiosReturn<AxiosResponseData, DeleteWorkflowParams> =>
|
||||
useApi<AxiosResponseData, DeleteWorkflowParams>('/v1/workflow/del_workflow', params)
|
||||
|
||||
/**
|
||||
@@ -75,7 +82,9 @@ export const getWorkflowHistoryDetail = (
|
||||
* @param {ExecuteWorkflowParams} [params] 请求参数
|
||||
* @returns {useAxiosReturn<AxiosResponseData, ExecuteWorkflowParams>} 手动执行工作流的组合式 API 调用封装。包含响应数据、加载状态及执行函数。
|
||||
*/
|
||||
export const executeWorkflow = (params?: ExecuteWorkflowParams): useAxiosReturn<AxiosResponseData, ExecuteWorkflowParams> =>
|
||||
export const executeWorkflow = (
|
||||
params?: ExecuteWorkflowParams,
|
||||
): useAxiosReturn<AxiosResponseData, ExecuteWorkflowParams> =>
|
||||
useApi<AxiosResponseData, ExecuteWorkflowParams>('/v1/workflow/execute_workflow', params)
|
||||
|
||||
/**
|
||||
@@ -93,5 +102,15 @@ export const updateWorkflowExecType = (
|
||||
* @param {EnableWorkflowParams} [params] 请求参数
|
||||
* @returns {useAxiosReturn<AxiosResponseData, EnableWorkflowParams>} 启用或禁用工作流的组合式 API 调用封装。包含响应数据、加载状态及执行函数。
|
||||
*/
|
||||
export const enableWorkflow = (params?: EnableWorkflowParams): useAxiosReturn<AxiosResponseData, EnableWorkflowParams> =>
|
||||
export const enableWorkflow = (
|
||||
params?: EnableWorkflowParams,
|
||||
): useAxiosReturn<AxiosResponseData, EnableWorkflowParams> =>
|
||||
useApi<AxiosResponseData, EnableWorkflowParams>('/v1/workflow/active', params)
|
||||
|
||||
/**
|
||||
* @description 停止工作流执行
|
||||
* @param {StopWorkflowParams} [params] 请求参数
|
||||
* @returns {useAxiosReturn<AxiosResponseData, StopWorkflowParams>} 停止工作流执行的组合式 API 调用封装。包含响应数据、加载状态及执行函数。
|
||||
*/
|
||||
export const stopWorkflow = (params?: StopWorkflowParams): useAxiosReturn<AxiosResponseData, StopWorkflowParams> =>
|
||||
useApi<AxiosResponseData, StopWorkflowParams>('/v1/workflow/stop', params)
|
||||
|
||||
@@ -0,0 +1,79 @@
|
||||
<svg width="64.000000pt" height="64.000000pt" viewBox="0 0 64.000000 64.000000" xmlns="http://www.w3.org/2000/svg">
|
||||
<g transform="translate(0.000000,64.000000) scale(0.100000,-0.100000)" fill="#fefefe" stroke="none">
|
||||
<path d="M0 320 l0 -320 320 0 320 0 0 320 0 320 -320 0 -320 0 0 -320z m205
|
||||
184 c-11 -9 -27 -21 -35 -27 -9 -7 -26 -25 -38 -41 l-22 -29 0 -55 0 -55 34
|
||||
-31 c39 -37 94 -56 162 -56 l49 0 42 19 c64 30 82 82 42 122 l-22 22 -74 -7
|
||||
-75 -6 -29 29 -29 29 9 24 c4 13 26 33 47 45 l39 23 47 0 47 0 56 -21 56 -21
|
||||
34 -33 c18 -19 38 -49 45 -69 l11 -35 -11 -43 -12 -43 -48 -46 -47 -47 -54
|
||||
-17 c-108 -36 -230 -16 -308 51 -45 39 -81 100 -81 136 1 35 34 100 66 129 25
|
||||
23 100 68 114 68 3 0 -4 -7 -15 -15z" />
|
||||
</g>
|
||||
<g transform="translate(0.000000,64.000000) scale(0.100000,-0.100000)" fill="#2470f0" stroke="none">
|
||||
<path d="M267 498 c-42 -21 -63 -55 -54 -90 10 -38 95 -75 111 -49 5 7 50 8
|
||||
98 2 4 -1 15 -12 23 -25 l16 -25 -11 -23 c-17 -32 -51 -58 -77 -58 -13 0 -23
|
||||
-4 -23 -10 l0 -10 -44 0 c-25 0 -48 5 -51 10 -3 6 -15 10 -26 10 -29 0 -87 41
|
||||
-98 70 -12 29 -14 44 -12 82 l1 27 30 34 c17 19 30 40 30 46 0 40 -99 -37
|
||||
-130 -101 l-18 -38 5 -42 6 -43 26 -35 c27 -36 71 -79 82 -80 4 0 24 -7 45
|
||||
-16 l39 -17 88 -1 c48 -1 87 2 87 7 0 4 8 7 18 7 27 0 117 56 135 84 9 14 23
|
||||
44 32 68 l14 43 -11 35 c-7 19 -23 50 -36 69 l-25 33 -46 22 c-25 11 -50 21
|
||||
-56 22 -5 1 -12 3 -15 4 -3 1 -30 3 -60 4 l-55 2 -38 -18z" />
|
||||
</g>
|
||||
<g transform="translate(0.000000,64.000000) scale(0.100000,-0.100000)" fill="#2573f7" stroke="none">
|
||||
<path d="M159 505 c-25 -13 -60 -40 -77 -59 -30 -34 -52 -90 -52 -131 1 -38
|
||||
37 -101 81 -138 l43 -37 50 -15 c64 -19 169 -19 233 0 l50 15 45 40 c48 41 73
|
||||
86 65 117 l-4 18 -7 -20 c-4 -11 -15 -35 -24 -54 l-17 -35 -45 -28 c-25 -16
|
||||
-57 -32 -72 -35 -16 -3 -28 -8 -28 -12 0 -3 -35 -5 -78 -4 l-77 1 -45 18 c-25
|
||||
10 -46 17 -47 16 -6 -5 -103 105 -98 110 2 2 0 19 -4 38 l-7 35 14 30 c17 35
|
||||
69 92 97 107 l20 11 -26 -29 c-35 -38 -52 -72 -43 -85 l7 -12 13 29 c17 38 31
|
||||
54 77 88 20 16 37 32 37 37 0 16 -33 9 -81 -16z" />
|
||||
<path d="M277 506 c-49 -18 -67 -34 -67 -60 l0 -21 23 27 c12 15 36 33 52 39
|
||||
33 12 101 15 127 4 9 -4 22 -4 28 0 5 3 10 2 10 -2 0 -8 41 -27 63 -31 14 -1
|
||||
66 -76 67 -94 0 -9 5 -20 10 -23 l10 -6 0 23 c0 13 -11 40 -25 60 l-25 36 -53
|
||||
26 -53 26 -64 5 -65 5 -38 -14z" />
|
||||
<path d="M210 409 c0 -23 32 -48 65 -51 53 -3 95 2 95 12 0 13 -47 13 -54 1
|
||||
-4 -5 -12 -8 -19 -7 -20 3 -61 28 -74 45 l-12 16 -1 -16z" />
|
||||
<path d="M380 371 c0 -5 11 -12 25 -15 13 -3 30 -16 36 -27 l11 -22 -11 -23
|
||||
c-5 -13 -28 -32 -50 -44 l-40 -20 -51 0 -50 0 -45 21 c-48 22 -85 61 -85 87
|
||||
l0 16 -13 -13 -12 -13 13 -5 c6 -3 10 -8 7 -13 -5 -9 51 -67 60 -62 3 1 13 -4
|
||||
22 -13 8 -9 22 -14 29 -11 7 3 16 1 19 -4 4 -6 31 -10 61 -10 l54 0 0 11 c0 5
|
||||
5 7 10 4 16 -10 75 31 88 60 17 38 15 53 -13 80 -23 24 -65 34 -65 16z" />
|
||||
</g>
|
||||
<g transform="translate(0.000000,64.000000) scale(0.100000,-0.100000)" fill="#2a74f0" stroke="none">
|
||||
<path d="M164 504 l-19 -15 24 7 24 6 -7 -11 c-4 -6 -3 -11 3 -11 5 0 13 5 16
|
||||
10 3 6 1 10 -5 10 -6 0 -8 5 -5 10 9 15 -9 12 -31 -6z" />
|
||||
<path d="M290 510 c0 -5 4 -10 9 -10 6 0 13 5 16 10 l6 10 -15 0 c-9 0 -16 -4
|
||||
-16 -10z" />
|
||||
<path d="M395 510 c3 -5 10 -10 16 -10 5 0 9 5 9 10 0 6 -7 10 -16 10 l-15 0
|
||||
6 -10z" />
|
||||
<path d="M474 485 c11 -8 25 -15 30 -15 6 0 2 7 -8 15 -11 8 -25 15 -30 15 -6
|
||||
0 -2 -7 8 -15z" />
|
||||
<path d="M70 428 c-16 -22 -30 -46 -29 -52 0 -6 6 -2 12 8 7 11 25 34 41 53
|
||||
15 18 23 33 17 33 -6 0 -24 -19 -41 -42z" />
|
||||
<path d="M205 437 c-4 -10 -5 -21 -1 -24 10 -10 18 4 13 24 l-4 18 -8 -18z" />
|
||||
<path d="M120 420 c-6 -12 -9 -24 -7 -27 3 -2 11 5 17 17 6 12 9 24 7 27 -3 2
|
||||
-11 -5 -17 -17z" />
|
||||
<path d="M260 360 c0 -5 7 -10 16 -10 l15 0 -6 10 c-3 6 -10 10 -16 10 -5 0
|
||||
-9 -4 -9 -10z" />
|
||||
<path d="M100 351 c0 -6 5 -13 10 -16 l10 -6 0 15 c0 9 -4 16 -10 16 -5 0 -10
|
||||
-4 -10 -9z" />
|
||||
<path d="M592 330 c1 -16 5 -30 10 -30 4 0 8 14 8 30 0 17 -4 30 -9 30 -5 0
|
||||
-9 -13 -9 -30z" />
|
||||
<path d="M30 296 c0 -9 5 -16 10 -16 6 0 10 4 10 9 0 6 -4 13 -10 16 l-10 6 0
|
||||
-15z" />
|
||||
<path d="M130 282 c0 -12 19 -26 26 -19 2 2 -2 10 -11 17 l-15 12 0 -10z" />
|
||||
<path d="M425 260 c-10 -11 -13 -20 -8 -20 13 0 38 29 31 35 -3 3 -13 -4 -23
|
||||
-15z" />
|
||||
<path d="M566 234 c-10 -14 -16 -28 -13 -30 2 -3 12 7 21 22 10 14 16 28 13
|
||||
30 -2 3 -12 -7 -21 -22z" />
|
||||
<path d="M70 221 c0 -5 5 -13 10 -16 6 -3 10 -2 10 4 0 5 -4 13 -10 16 -5 3
|
||||
-10 2 -10 -4z" />
|
||||
<path d="M105 180 c3 -5 11 -10 16 -10 6 0 7 5 4 10 -3 6 -11 10 -16 10 -6 0
|
||||
-7 -4 -4 -10z" />
|
||||
<path d="M515 180 c-3 -5 -2 -10 4 -10 5 0 13 5 16 10 3 6 2 10 -4 10 -5 0
|
||||
-13 -4 -16 -10z" />
|
||||
<path d="M195 130 c3 -5 11 -10 16 -10 6 0 7 5 4 10 -3 6 -11 10 -16 10 -6 0
|
||||
-7 -4 -4 -10z" />
|
||||
<path d="M425 130 c-3 -5 -2 -10 4 -10 5 0 13 5 16 10 3 6 2 10 -4 10 -5 0
|
||||
-13 -4 -16 -10z" />
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 4.7 KiB |
@@ -0,0 +1 @@
|
||||
<svg class="icon" width="30" height="30" viewBox="0 0 1024 1024" xmlns="http://www.w3.org/2000/svg"><path d="M803.6 859.2c0 26.6-20.4 49.2-48.4 51.8-21.2 2-48.6-11-54.8-39.8-5.6-26-13.2-50.8-29-72.4-6-8.2-12.8-16-20-23.4-7.6-8-9.4-14-4.4-19.8 5-5.8 12.8-5 20.8 3.2 20.8 21 45.4 35.2 73.6 43.6 7.2 2.2 14.8 3.4 22.2 5.2 24.6 6.2 40 26.2 40 51.6z" fill="#FC6401"/><path d="M698.2 549.8c.2-28.4 20.8-50.2 49.6-52.6 25.6-2.2 50.6 17.6 55 45.2 6 36.2 22.8 66.2 48.4 92 3.2 3.2 5.6 9.2 5.2 13.8-.4 7.2-9.8 10.6-16.2 6.4-3.4-2.2-6.2-5-9-7.8-25.4-24.6-55.6-39.4-90.4-45.4-24.8-4.6-42.6-26.2-42.6-51.6z" fill="#2DBD00"/><path d="M595.4 765.2c-26.6 0-49.2-20.4-51.8-48.4-2-21.2 11-48.6 39.8-54.8 26-5.6 50.8-13.2 72.4-29 8.2-6 16-12.8 23.4-20 8-7.6 14-9.4 19.8-4.4 5.8 5 5 12.8-3.2 20.8-21 20.8-35.2 45.4-43.6 73.6-2.2 7.2-3.4 14.8-5.2 22.2-6.2 24.6-26.2 40-51.6 40z" fill="#FFCD00"/><path d="M898.8 650c28.4.2 50.2 20.8 52.6 49.6 2.2 25.6-17.6 50.6-45.2 55-36.2 6-66.2 22.8-92 48.4-3.2 3.2-9.2 5.6-13.8 5.2-7.2-.4-10.6-9.8-6.4-16.2 2.2-3.4 5-6.2 7.8-9 24.6-25.4 39.4-55.6 45.4-90.4 4.6-25 26.2-42.8 51.6-42.6z" fill="#0084F0"/><path d="M734 208.6c-110.4-108.4-244.8-139.8-392.4-100-260 70.2-340.4 340.6-209 517 6.4 8.6 7.6 24.4 5.2 35.4-7 32.4-17.4 64.2-26 96.2-4.6 17.2-7.4 34.6 8 48.4 16.6 14.8 34.2 11.8 52.2 2.6 29.6-15 59.8-29.2 89-45 19-10.4 36.2-10.8 57.6-4.8 42.8 11.8 87.2 18.4 109.6 23 43.8-.8 83.6-5.2 120.2-13.6-13.8-12-23-29.2-24.8-49-.4-5.4-.2-10.8.6-16.2C466.4 715 405 710 341 688.6c-42.2-14.2-76.8-17.8-113.4 7-3.4 2.2-7.8 2.8-24.6 8.2 33.8-58.4 8.8-95-19.6-136.6-63.4-92-50.4-210.8 24.6-296.4C330.8 131 571 131 693.8 271c52.8 60.2 73.6 135.2 61.8 206.2 28 1.6 52.8 20.6 63 47.2 32-108.8 4-228.8-84.6-315.8z" fill="#0083EF"/></svg>
|
||||
|
After Width: | Height: | Size: 1.7 KiB |
@@ -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解析服务器
|
||||
|
||||
@@ -191,6 +191,36 @@ export const ApiProjectConfig: Record<string, ApiProjectType> = {
|
||||
type: ['dns'],
|
||||
sort: 20,
|
||||
},
|
||||
namesilo: {
|
||||
name: 'Namesilo',
|
||||
icon: 'namesilo',
|
||||
type: ['dns'],
|
||||
sort: 21,
|
||||
},
|
||||
namedotcom: {
|
||||
name: 'Name.com',
|
||||
icon: 'namedotcom',
|
||||
type: ['dns'],
|
||||
sort: 22,
|
||||
},
|
||||
bunny: {
|
||||
name: 'Bunny',
|
||||
icon: 'bunny',
|
||||
type: ['dns'],
|
||||
sort: 23,
|
||||
},
|
||||
gcore: {
|
||||
name: 'Gcore',
|
||||
icon: 'gcore',
|
||||
type: ['dns'],
|
||||
sort: 24,
|
||||
},
|
||||
jdcloud: {
|
||||
name: '京东云',
|
||||
icon: 'jdcloud',
|
||||
type: ['dns'],
|
||||
sort: 25,
|
||||
},
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -633,5 +633,16 @@
|
||||
"t_3_1748591484673": "Webhook",
|
||||
"t_4_1748591492587": "جارٍ اختبار إشعار {type}",
|
||||
"t_5_1748591491370": "اختبار{type}",
|
||||
"t_0_1748591669194": "إرسال رسالة اختبار إلى، التكوين الحالي {type} إشعار، هل تتابع؟"
|
||||
"t_0_1748591669194": "إرسال رسالة اختبار إلى، التكوين الحالي {type} إشعار، هل تتابع؟",
|
||||
"t_0_1749119980577": "خطأ في تنسيق عنوان IP الخادم أو اسم النطاق",
|
||||
"t_0_1749204565782": "إيقاف التنفيذ",
|
||||
"t_1_1749204570473": "هل أنت متأكد أنك تريد إيقاف تنفيذ سير العمل الحالي؟",
|
||||
"t_2_1749204567193": "تعطيل دعم CNAME",
|
||||
"t_0_1749263105073": "وقت انتهاء الفحص المسبق (ثانية)",
|
||||
"t_1_1749263104936": "الرجاء إدخال مهلة التحقق المسبق",
|
||||
"t_2_1749263103765": "تجاهل نتائج الفحص المسبق",
|
||||
"t_3_1749263104237": "عندما تفشل الفحص المسبق",
|
||||
"t_4_1749263101853": "استمر",
|
||||
"t_5_1749263101934": "توقف",
|
||||
"t_6_1749263103891": "إرسال طلب التحقق إلى CA"
|
||||
}
|
||||
@@ -633,5 +633,16 @@
|
||||
"t_3_1748591484673": "Webhook",
|
||||
"t_4_1748591492587": "Testing {type} notification",
|
||||
"t_5_1748591491370": "Test{type}",
|
||||
"t_0_1748591669194": "Send test message to, current configuration {type} notification, continue?"
|
||||
"t_0_1748591669194": "Send test message to, current configuration {type} notification, continue?",
|
||||
"t_0_1749119980577": "Server IP address or domain name format error",
|
||||
"t_0_1749204565782": "Stop execution",
|
||||
"t_1_1749204570473": "Are you sure you want to stop the execution of the current workflow?",
|
||||
"t_2_1749204567193": "Disable CNAME support",
|
||||
"t_0_1749263105073": "Pre-check timeout (seconds)",
|
||||
"t_1_1749263104936": "Please enter the pre-check timeout",
|
||||
"t_2_1749263103765": "Ignore pre-check results",
|
||||
"t_3_1749263104237": "When the pre-check fails",
|
||||
"t_4_1749263101853": "Continue",
|
||||
"t_5_1749263101934": "Stop",
|
||||
"t_6_1749263103891": "Initiate verification request to CA"
|
||||
}
|
||||
@@ -633,5 +633,16 @@
|
||||
"t_3_1748591484673": "Webhook",
|
||||
"t_4_1748591492587": "Probando notificación {type}",
|
||||
"t_5_1748591491370": "Prueba{type}",
|
||||
"t_0_1748591669194": "Enviar mensaje de prueba a, configuración actual {type} notificación, ¿continuar?"
|
||||
"t_0_1748591669194": "Enviar mensaje de prueba a, configuración actual {type} notificación, ¿continuar?",
|
||||
"t_0_1749119980577": "Error de formato de dirección IP o nombre de dominio del servidor",
|
||||
"t_0_1749204565782": "Detener ejecución",
|
||||
"t_1_1749204570473": "¿Estás seguro de que quieres detener la ejecución del flujo de trabajo actual?",
|
||||
"t_2_1749204567193": "Deshabilitar soporte CNAME",
|
||||
"t_0_1749263105073": "Tiempo de espera de la preverificación (segundos)",
|
||||
"t_1_1749263104936": "Introduce el tiempo de espera de la comprobación previa",
|
||||
"t_2_1749263103765": "Ignorar los resultados de la verificación previa",
|
||||
"t_3_1749263104237": "Cuando falla la verificación previa",
|
||||
"t_4_1749263101853": "Continuar",
|
||||
"t_5_1749263101934": "Detener",
|
||||
"t_6_1749263103891": "Enviar solicitud de verificación a CA"
|
||||
}
|
||||
@@ -633,5 +633,16 @@
|
||||
"t_3_1748591484673": "Webhook",
|
||||
"t_4_1748591492587": "Test de la notification {type}",
|
||||
"t_5_1748591491370": "Test{type}",
|
||||
"t_0_1748591669194": "Envoyer un message test à, configuration actuelle {type} notification, continuer ?"
|
||||
"t_0_1748591669194": "Envoyer un message test à, configuration actuelle {type} notification, continuer ?",
|
||||
"t_0_1749119980577": "Erreur de format d'adresse IP ou de nom de domaine du serveur",
|
||||
"t_0_1749204565782": "Arrêter l'exécution",
|
||||
"t_1_1749204570473": "Êtes-vous sûr de vouloir arrêter l'exécution du workflow actuel ?",
|
||||
"t_2_1749204567193": "Désactiver la prise en charge CNAME",
|
||||
"t_0_1749263105073": "Délai d'expiration de la pré-vérification (secondes)",
|
||||
"t_1_1749263104936": "Veuillez entrer le délai d'attente de pré-vérification",
|
||||
"t_2_1749263103765": "Ignorer les résultats de la pré-vérification",
|
||||
"t_3_1749263104237": "Lorsque la pré-vérification échoue",
|
||||
"t_4_1749263101853": "Continuer",
|
||||
"t_5_1749263101934": "Arrêter",
|
||||
"t_6_1749263103891": "Envoyer une demande de vérification à CA"
|
||||
}
|
||||
@@ -633,5 +633,16 @@
|
||||
"t_3_1748591484673": "Webhook",
|
||||
"t_4_1748591492587": "{type}通知をテスト中",
|
||||
"t_5_1748591491370": "テスト{type}",
|
||||
"t_0_1748591669194": "テストメッセージを送信します、現在の設定 {type} 通知、続行しますか?"
|
||||
"t_0_1748591669194": "テストメッセージを送信します、現在の設定 {type} 通知、続行しますか?",
|
||||
"t_0_1749119980577": "サーバーのIPアドレスまたはドメイン名の形式が正しくありません",
|
||||
"t_0_1749204565782": "実行を停止",
|
||||
"t_1_1749204570473": "現在のワークフローの実行を停止しますか?",
|
||||
"t_2_1749204567193": "CNAMEサポートを無効にする",
|
||||
"t_0_1749263105073": "事前チェックのタイムアウト時間(秒)",
|
||||
"t_1_1749263104936": "事前チェックのタイムアウト時間を入力してください",
|
||||
"t_2_1749263103765": "事前チェック結果を無視",
|
||||
"t_3_1749263104237": "事前チェックが失敗した場合",
|
||||
"t_4_1749263101853": "続ける",
|
||||
"t_5_1749263101934": "停止",
|
||||
"t_6_1749263103891": "CAに検証リクエストを送信する"
|
||||
}
|
||||
@@ -633,5 +633,16 @@
|
||||
"t_3_1748591484673": "Webhook",
|
||||
"t_4_1748591492587": "{type} 알림 테스트 중",
|
||||
"t_5_1748591491370": "테스트{type}",
|
||||
"t_0_1748591669194": "테스트 메시지를 보냅니다, 현재 구성 {type} 알림, 계속하시겠습니까?"
|
||||
"t_0_1748591669194": "테스트 메시지를 보냅니다, 현재 구성 {type} 알림, 계속하시겠습니까?",
|
||||
"t_0_1749119980577": "서버 IP 주소 또는 도메인 이름 형식 오류",
|
||||
"t_0_1749204565782": "실행 중지",
|
||||
"t_1_1749204570473": "현재 워크플로우 실행을 중지하시겠습니까?",
|
||||
"t_2_1749204567193": "CNAME 지원 비활성화",
|
||||
"t_0_1749263105073": "사전 점검 시간 초과 (초)",
|
||||
"t_1_1749263104936": "사전 검사 시간 초과 시간을 입력하십시오",
|
||||
"t_2_1749263103765": "사전 점검 결과 무시",
|
||||
"t_3_1749263104237": "사전 점검이 실패했을 때",
|
||||
"t_4_1749263101853": "계속하다",
|
||||
"t_5_1749263101934": "중지",
|
||||
"t_6_1749263103891": "CA에 검증 요청 시작"
|
||||
}
|
||||
@@ -633,5 +633,16 @@
|
||||
"t_3_1748591484673": "Webhook",
|
||||
"t_4_1748591492587": "Testando notificação {type}",
|
||||
"t_5_1748591491370": "Teste{type}",
|
||||
"t_0_1748591669194": "Enviar mensagem de teste para, configuração atual {type} notificação, continuar?"
|
||||
"t_0_1748591669194": "Enviar mensagem de teste para, configuração atual {type} notificação, continuar?",
|
||||
"t_0_1749119980577": "Erro de formato de endereço IP ou nome de domínio do servidor",
|
||||
"t_0_1749204565782": "Parar execução",
|
||||
"t_1_1749204570473": "Tem certeza de que deseja interromper a execução do fluxo de trabalho atual?",
|
||||
"t_2_1749204567193": "Desativar suporte CNAME",
|
||||
"t_0_1749263105073": "Tempo limite de pré-verificação (segundos)",
|
||||
"t_1_1749263104936": "Insira o tempo limite de pré-verificação",
|
||||
"t_2_1749263103765": "Ignorar resultados de pré-verificação",
|
||||
"t_3_1749263104237": "Quando a pré-verificação falha",
|
||||
"t_4_1749263101853": "Continuar",
|
||||
"t_5_1749263101934": "Parar",
|
||||
"t_6_1749263103891": "Enviar solicitação de verificação para CA"
|
||||
}
|
||||
@@ -633,5 +633,16 @@
|
||||
"t_3_1748591484673": "Webhook",
|
||||
"t_4_1748591492587": "Тестирование уведомления {type}",
|
||||
"t_5_1748591491370": "Тест{type}",
|
||||
"t_0_1748591669194": "Отправить тестовое сообщение, текущая конфигурация {type} уведомления, продолжить?"
|
||||
"t_0_1748591669194": "Отправить тестовое сообщение, текущая конфигурация {type} уведомления, продолжить?",
|
||||
"t_0_1749119980577": "Ошибка формата IP-адреса сервера или доменного имени",
|
||||
"t_0_1749204565782": "Остановить выполнение",
|
||||
"t_1_1749204570473": "Вы уверены, что хотите остановить выполнение текущего рабочего процесса?",
|
||||
"t_2_1749204567193": "Отключить поддержку CNAME",
|
||||
"t_0_1749263105073": "Таймаут предварительной проверки (секунды)",
|
||||
"t_1_1749263104936": "Введите время ожидания предварительной проверки",
|
||||
"t_2_1749263103765": "Игнорировать результаты предварительной проверки",
|
||||
"t_3_1749263104237": "Когда предварительная проверка не удалась",
|
||||
"t_4_1749263101853": "Продолжить",
|
||||
"t_5_1749263101934": "Остановить",
|
||||
"t_6_1749263103891": "Отправить запрос на проверку в CA"
|
||||
}
|
||||
@@ -633,5 +633,16 @@
|
||||
"t_3_1748591484673": "Webhook",
|
||||
"t_4_1748591492587": "正在测试{type}通知",
|
||||
"t_5_1748591491370": "测试{type}",
|
||||
"t_0_1748591669194": "发送测试信息到,当前配置{type}通知,是否继续?"
|
||||
"t_0_1748591669194": "发送测试信息到,当前配置{type}通知,是否继续?",
|
||||
"t_0_1749119980577": "服务器IP地址或域名格式错误",
|
||||
"t_0_1749204565782": "停止执行",
|
||||
"t_1_1749204570473": "确定要停止当前工作流的执行吗?",
|
||||
"t_2_1749204567193": "禁用CNAME支持",
|
||||
"t_0_1749263105073": "预检查超时时间(秒)",
|
||||
"t_1_1749263104936": "请输入预检查超时时间",
|
||||
"t_2_1749263103765": "忽略预检查结果",
|
||||
"t_3_1749263104237": "当预检查失败时",
|
||||
"t_4_1749263101853": "继续",
|
||||
"t_5_1749263101934": "停止",
|
||||
"t_6_1749263103891": "向CA发起验证请求"
|
||||
}
|
||||
@@ -632,5 +632,16 @@
|
||||
"t_3_1748591484673": "Webhook",
|
||||
"t_4_1748591492587": "正在測試{type}通知",
|
||||
"t_5_1748591491370": "測試{type}",
|
||||
"t_0_1748591669194": "發送測試信息到,當前配置{type}通知,是否繼續?"
|
||||
"t_0_1748591669194": "發送測試信息到,當前配置{type}通知,是否繼續?",
|
||||
"t_0_1749119980577": "伺服器IP位址或網域名稱格式錯誤",
|
||||
"t_0_1749204565782": "停止執行",
|
||||
"t_1_1749204570473": "確定要停止當前工作流的執行嗎?",
|
||||
"t_2_1749204567193": "禁用CNAME支援",
|
||||
"t_0_1749263105073": "預檢查超時時間(秒)",
|
||||
"t_1_1749263104936": "請輸入預檢查超時時間",
|
||||
"t_2_1749263103765": "忽略預檢查結果",
|
||||
"t_3_1749263104237": "當預檢查失敗時",
|
||||
"t_4_1749263101853": "繼續",
|
||||
"t_5_1749263101934": "停止",
|
||||
"t_6_1749263103891": "向CA發起驗證請求"
|
||||
}
|
||||
51
frontend/apps/allin-ssl/src/types/access.d.ts
vendored
51
frontend/apps/allin-ssl/src/types/access.d.ts
vendored
@@ -53,7 +53,12 @@ export interface AddAccessParams<
|
||||
| NS1AccessConfig
|
||||
| CloudnsAccessConfig
|
||||
| AwsAccessConfig
|
||||
| AzureAccessConfig,
|
||||
| AzureAccessConfig
|
||||
| NamesiloAccessConfig
|
||||
| NamedotcomAccessConfig
|
||||
| BunnyAccessConfig
|
||||
| GcoreAccessConfig
|
||||
| JdcloudAccessConfig,
|
||||
> {
|
||||
name: string
|
||||
type: string
|
||||
@@ -79,7 +84,12 @@ export interface UpdateAccessParams<
|
||||
| NS1AccessConfig
|
||||
| CloudnsAccessConfig
|
||||
| AwsAccessConfig
|
||||
| AzureAccessConfig,
|
||||
| AzureAccessConfig
|
||||
| NamesiloAccessConfig
|
||||
| NamedotcomAccessConfig
|
||||
| BunnyAccessConfig
|
||||
| GcoreAccessConfig
|
||||
| JdcloudAccessConfig,
|
||||
> extends AddAccessParams<T> {
|
||||
id: string
|
||||
}
|
||||
@@ -213,6 +223,43 @@ export interface AzureAccessConfig {
|
||||
environment: string
|
||||
}
|
||||
|
||||
/**
|
||||
* Namesilo授权配置
|
||||
*/
|
||||
export interface NamesiloAccessConfig {
|
||||
api_key: string
|
||||
}
|
||||
|
||||
/**
|
||||
* Name.com授权配置
|
||||
*/
|
||||
export interface NamedotcomAccessConfig {
|
||||
username: string
|
||||
api_token: string
|
||||
}
|
||||
|
||||
/**
|
||||
* Bunny授权配置
|
||||
*/
|
||||
export interface BunnyAccessConfig {
|
||||
api_key: string
|
||||
}
|
||||
|
||||
/**
|
||||
* Gcore授权配置
|
||||
*/
|
||||
export interface GcoreAccessConfig {
|
||||
api_token: string
|
||||
}
|
||||
|
||||
/**
|
||||
* 京东云授权配置
|
||||
*/
|
||||
export interface JdcloudAccessConfig {
|
||||
access_key_id: string
|
||||
secret_access_key: string
|
||||
}
|
||||
|
||||
/** 删除授权请求参数 */
|
||||
export interface DeleteAccessParams {
|
||||
id: string
|
||||
|
||||
27
frontend/apps/allin-ssl/src/types/setting.d.ts
vendored
27
frontend/apps/allin-ssl/src/types/setting.d.ts
vendored
@@ -87,6 +87,14 @@ export interface ReportWebhook {
|
||||
ignore_ssl: boolean
|
||||
}
|
||||
|
||||
/** 企业微信通知配置 */
|
||||
export interface ReportWecom {
|
||||
name?: string
|
||||
enabled: string
|
||||
url: string
|
||||
data: string
|
||||
}
|
||||
|
||||
/** 添加告警请求参数 */
|
||||
export interface AddReportParams<T = string> {
|
||||
name: string
|
||||
@@ -109,6 +117,25 @@ export interface TestReportParams {
|
||||
id: number
|
||||
}
|
||||
|
||||
/** 获取版本信息请求参数 */
|
||||
export interface GetVersionParams {
|
||||
// 无参数
|
||||
}
|
||||
|
||||
/** 版本信息数据 */
|
||||
export interface VersionData {
|
||||
date: string // 版本日期
|
||||
log: string // 更新日志
|
||||
new_version: string // 新版本号
|
||||
update: string // 是否有更新 "1" 表示有更新,"0" 表示无更新
|
||||
version: string // 当前版本号
|
||||
}
|
||||
|
||||
/** 获取版本信息响应 */
|
||||
export interface GetVersionResponse extends AxiosResponseData {
|
||||
data: VersionData
|
||||
}
|
||||
|
||||
/** 消息通知选项 */
|
||||
export interface NotifyProviderOption {
|
||||
label: string
|
||||
|
||||
@@ -81,7 +81,7 @@ export interface WorkflowHistoryItem {
|
||||
create_time: number
|
||||
end_time: string
|
||||
exec_type: 'auto' | 'manual'
|
||||
status: 'success' | 'failed' | 'pending'
|
||||
status: 'success' | 'failed' | 'running'
|
||||
workflow_id: string
|
||||
}
|
||||
|
||||
@@ -112,3 +112,8 @@ export interface EnableWorkflowParams {
|
||||
active: string
|
||||
}
|
||||
|
||||
/** 停止工作流请求参数 */
|
||||
export interface StopWorkflowParams {
|
||||
id: string
|
||||
}
|
||||
|
||||
|
||||
@@ -27,7 +27,7 @@ import {
|
||||
useLoadingMask,
|
||||
} from '@baota/naive-ui/hooks'
|
||||
import { useError } from '@baota/hooks/error'
|
||||
import { isEmail, isIp, isPort, isUrl } from '@baota/utils/business'
|
||||
import { isEmail, isIp, isPort, isUrl, isDomain } from '@baota/utils/business'
|
||||
import { $t } from '@locales/index'
|
||||
import { useStore } from './useStore'
|
||||
import { ApiProjectConfig } from '@config/data'
|
||||
@@ -42,6 +42,11 @@ import type {
|
||||
CloudnsAccessConfig,
|
||||
AwsAccessConfig,
|
||||
AzureAccessConfig,
|
||||
NamesiloAccessConfig,
|
||||
NamedotcomAccessConfig,
|
||||
BunnyAccessConfig,
|
||||
GcoreAccessConfig,
|
||||
JdcloudAccessConfig,
|
||||
} from '@/types/access'
|
||||
import type { VNode, Ref } from 'vue'
|
||||
import { testAccess } from '@/api/access'
|
||||
@@ -306,8 +311,8 @@ export const useApiFormController = (props: ApiFormControllerProps): ApiFormCont
|
||||
required: true,
|
||||
trigger: 'input',
|
||||
validator: (rule: FormItemRule, value: string, callback: (error?: Error) => void) => {
|
||||
if (!isIp(value)) {
|
||||
return callback(new Error($t('t_0_1745317313835')))
|
||||
if (!isIp(value) && !isDomain(value)) {
|
||||
return callback(new Error($t('t_0_1749119980577')))
|
||||
}
|
||||
callback()
|
||||
},
|
||||
@@ -663,6 +668,27 @@ export const useApiFormController = (props: ApiFormControllerProps): ApiFormCont
|
||||
useFormInput('Environment', 'config.environment', { allowInput: noSideSpace, placeholder: 'public' }),
|
||||
)
|
||||
break
|
||||
case 'namesilo':
|
||||
items.push(useFormInput('API Key', 'config.api_key', { allowInput: noSideSpace }))
|
||||
break
|
||||
case 'namedotcom':
|
||||
items.push(
|
||||
useFormInput('Username', 'config.username', { allowInput: noSideSpace }),
|
||||
useFormInput('API Token', 'config.api_token', { allowInput: noSideSpace }),
|
||||
)
|
||||
break
|
||||
case 'bunny':
|
||||
items.push(useFormInput('API Key', 'config.api_key', { allowInput: noSideSpace }))
|
||||
break
|
||||
case 'gcore':
|
||||
items.push(useFormInput('API Token', 'config.api_token', { allowInput: noSideSpace }))
|
||||
break
|
||||
case 'jdcloud':
|
||||
items.push(
|
||||
useFormInput('Access Key ID', 'config.access_key_id', { allowInput: noSideSpace }),
|
||||
useFormInput('Secret Access Key', 'config.secret_access_key', { allowInput: noSideSpace }),
|
||||
)
|
||||
break
|
||||
default:
|
||||
break
|
||||
}
|
||||
@@ -760,6 +786,33 @@ export const useApiFormController = (props: ApiFormControllerProps): ApiFormCont
|
||||
environment: '',
|
||||
} as AzureAccessConfig
|
||||
break
|
||||
case 'namesilo':
|
||||
param.value.config = {
|
||||
api_key: '',
|
||||
} as NamesiloAccessConfig
|
||||
break
|
||||
case 'namedotcom':
|
||||
param.value.config = {
|
||||
username: '',
|
||||
api_token: '',
|
||||
} as NamedotcomAccessConfig
|
||||
break
|
||||
case 'bunny':
|
||||
param.value.config = {
|
||||
api_key: '',
|
||||
} as BunnyAccessConfig
|
||||
break
|
||||
case 'gcore':
|
||||
param.value.config = {
|
||||
api_token: '',
|
||||
} as GcoreAccessConfig
|
||||
break
|
||||
case 'jdcloud':
|
||||
param.value.config = {
|
||||
access_key_id: '',
|
||||
secret_access_key: '',
|
||||
} as JdcloudAccessConfig
|
||||
break
|
||||
}
|
||||
},
|
||||
)
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { NFormItem, NInputNumber } from 'naive-ui'
|
||||
import { NFormItem, NInputNumber, NSwitch } from 'naive-ui'
|
||||
import { useForm, useFormHooks, useModalHooks } from '@baota/naive-ui/hooks'
|
||||
import { useStore } from '@components/FlowChart/useStore'
|
||||
import { $t } from '@locales/index'
|
||||
@@ -29,6 +29,9 @@ export default defineComponent({
|
||||
name_server: '',
|
||||
skip_check: 0,
|
||||
algorithm: 'RSA2048',
|
||||
close_cname: 0,
|
||||
max_wait: undefined,
|
||||
ignore_check: 0,
|
||||
},
|
||||
}),
|
||||
},
|
||||
@@ -86,7 +89,8 @@ export default defineComponent({
|
||||
'onUpdate:value': (val: { value: string; ca: string; email: string }) => {
|
||||
param.value.eabId = val.value
|
||||
param.value.ca = val.ca
|
||||
if (val.value) param.value.email = val.email
|
||||
// 始终更新邮件,确保 Let's Encrypt 和 Buypass 的邮件能正确显示
|
||||
param.value.email = val.email
|
||||
},
|
||||
}}
|
||||
/>
|
||||
@@ -138,15 +142,12 @@ export default defineComponent({
|
||||
},
|
||||
{ showRequireMark: false },
|
||||
),
|
||||
useFormInput(
|
||||
$t('t_0_1747106957037'),
|
||||
'name_server',
|
||||
useFormSwitch(
|
||||
$t('t_2_1749204567193'),
|
||||
'close_cname',
|
||||
{
|
||||
placeholder: $t('t_1_1747106961747'),
|
||||
allowInput: noSideSpace,
|
||||
onInput: (val: string) => {
|
||||
param.value.name_server = val.replace(/,/g, ',').replace(/;/g, ',') // 中文逗号分隔
|
||||
},
|
||||
checkedValue: 1,
|
||||
uncheckedValue: 0,
|
||||
},
|
||||
{ showRequireMark: false },
|
||||
),
|
||||
@@ -159,6 +160,62 @@ export default defineComponent({
|
||||
},
|
||||
{ showRequireMark: false },
|
||||
),
|
||||
// 只有在跳过预检查关闭时才显示DNS递归服务器、预检查超时时间和忽略预检查结果
|
||||
...(param.value.skip_check === 0
|
||||
? [
|
||||
useFormInput(
|
||||
$t('t_0_1747106957037'),
|
||||
'name_server',
|
||||
{
|
||||
placeholder: $t('t_1_1747106961747'),
|
||||
allowInput: noSideSpace,
|
||||
onInput: (val: string) => {
|
||||
param.value.name_server = val.replace(/,/g, ',').replace(/;/g, ',') // 中文逗号分隔
|
||||
},
|
||||
},
|
||||
{ showRequireMark: false },
|
||||
),
|
||||
{
|
||||
type: 'custom' as const,
|
||||
render: () => {
|
||||
return (
|
||||
<NFormItem label={$t('t_0_1749263105073')} path="max_wait">
|
||||
<NInputNumber
|
||||
v-model:value={(param.value as ApplyNodeConfig & { max_wait?: number }).max_wait}
|
||||
showButton={false}
|
||||
min={1}
|
||||
class="w-full"
|
||||
placeholder={$t('t_1_1749263104936')}
|
||||
/>
|
||||
</NFormItem>
|
||||
)
|
||||
},
|
||||
},
|
||||
{
|
||||
type: 'custom' as const,
|
||||
render: () => {
|
||||
return (
|
||||
<NFormItem label={$t('t_2_1749263103765')} path="ignore_check">
|
||||
<div class="flex items-center">
|
||||
<span class="text-[1.4rem] mr-[1.2rem]">{$t('t_3_1749263104237')}</span>
|
||||
<NSwitch
|
||||
v-model:value={param.value.ignore_check}
|
||||
checkedValue={1}
|
||||
uncheckedValue={0}
|
||||
class="mx-[.5rem]"
|
||||
v-slots={{
|
||||
checked: () => $t('t_4_1749263101853'),
|
||||
unchecked: () => $t('t_5_1749263101934'),
|
||||
}}
|
||||
/>
|
||||
<span class="text-[1.4rem] ml-[1.2rem]">{$t('t_6_1749263103891')}</span>
|
||||
</div>
|
||||
</NFormItem>
|
||||
)
|
||||
},
|
||||
},
|
||||
]
|
||||
: []),
|
||||
]
|
||||
: []),
|
||||
useFormHelp([
|
||||
@@ -183,6 +240,7 @@ export default defineComponent({
|
||||
confirm(async (close) => {
|
||||
try {
|
||||
await example.value?.validate()
|
||||
|
||||
updateNodeConfig(props.node.id, data.value) // 更新节点配置
|
||||
isRefreshNode.value = props.node.id // 刷新节点
|
||||
close()
|
||||
|
||||
@@ -35,6 +35,7 @@ const {
|
||||
workflowFormData,
|
||||
deleteExistingWorkflow,
|
||||
executeExistingWorkflow,
|
||||
stopExistingWorkflow,
|
||||
setWorkflowActive,
|
||||
setWorkflowExecType,
|
||||
caFormData,
|
||||
@@ -220,7 +221,7 @@ export const useController = () => {
|
||||
useModal({
|
||||
title: workflow ? `【${workflow.name}】 - ${$t('t_9_1745215914666')}` : $t('t_9_1745215914666'),
|
||||
component: HistoryModal,
|
||||
area: 800,
|
||||
area: 850,
|
||||
componentProps: { id: workflow.id.toString() },
|
||||
})
|
||||
}
|
||||
@@ -422,6 +423,23 @@ export const useHistoryController = (id: string) => {
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* @description 停止工作流执行
|
||||
* @param {WorkflowHistoryItem} historyItem - 工作流历史记录项
|
||||
*/
|
||||
const handleStopWorkflow = async (historyItem: WorkflowHistoryItem) => {
|
||||
useDialog({
|
||||
title: $t('t_0_1749204565782'),
|
||||
content: $t('t_1_1749204570473'),
|
||||
onPositiveClick: async () => {
|
||||
await stopExistingWorkflow(historyItem.id)
|
||||
await fetch() // 刷新历史记录表格
|
||||
// 触发外部主表格刷新
|
||||
refreshTable.value = true
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* @description 创建历史记录表格列配置
|
||||
* @returns {DataTableColumn<WorkflowHistoryItem>[]} 返回表格列配置数组
|
||||
@@ -430,7 +448,7 @@ export const useHistoryController = (id: string) => {
|
||||
{
|
||||
title: $t('t_4_1745227838558'),
|
||||
key: 'create_time',
|
||||
width: 230,
|
||||
width: 200,
|
||||
render: (row: WorkflowHistoryItem) => {
|
||||
// 处理数字类型的时间戳
|
||||
return row.create_time ? row.create_time : '-'
|
||||
@@ -439,7 +457,7 @@ export const useHistoryController = (id: string) => {
|
||||
{
|
||||
title: $t('t_5_1745227839906'),
|
||||
key: 'end_time',
|
||||
width: 230,
|
||||
width: 200,
|
||||
render: (row: WorkflowHistoryItem) => {
|
||||
// 处理数字类型的时间戳
|
||||
return row.end_time ? row.end_time : '-'
|
||||
@@ -448,7 +466,7 @@ export const useHistoryController = (id: string) => {
|
||||
{
|
||||
title: $t('t_6_1745227838798'),
|
||||
key: 'exec_type',
|
||||
width: 110,
|
||||
width: 120,
|
||||
render: (row: WorkflowHistoryItem) => (
|
||||
<NTag type={row.exec_type === 'auto' ? 'info' : 'default'} size="small" bordered={false}>
|
||||
{row.exec_type === 'auto' ? $t('t_2_1745215915397') : $t('t_3_1745215914237')}
|
||||
@@ -461,9 +479,14 @@ export const useHistoryController = (id: string) => {
|
||||
key: 'actions',
|
||||
fixed: 'right',
|
||||
align: 'right',
|
||||
width: 80,
|
||||
width: 180,
|
||||
render: (row: WorkflowHistoryItem) => (
|
||||
<NSpace justify="end">
|
||||
<NSpace justify="end" size="small">
|
||||
{row.status === 'running' && (
|
||||
<NButton size="tiny" strong secondary type="error" onClick={() => handleStopWorkflow(row)}>
|
||||
{$t('t_0_1749204565782')}
|
||||
</NButton>
|
||||
)}
|
||||
<NButton
|
||||
size="tiny"
|
||||
strong
|
||||
|
||||
@@ -5,6 +5,7 @@ import {
|
||||
executeWorkflow,
|
||||
updateWorkflowExecType,
|
||||
enableWorkflow,
|
||||
stopWorkflow,
|
||||
} from '@/api/workflow'
|
||||
import { getEabList, addEab, deleteEab } from '@/api/access'
|
||||
import { useError } from '@baota/hooks/error'
|
||||
@@ -17,6 +18,7 @@ import type {
|
||||
WorkflowItem,
|
||||
UpdateWorkflowExecTypeParams,
|
||||
EnableWorkflowParams,
|
||||
StopWorkflowParams,
|
||||
} from '@/types/workflow'
|
||||
import type { EabItem, EabListParams, EabAddParams } from '@/types/access'
|
||||
import type { TableResponse } from '@baota/naive-ui/types/table'
|
||||
@@ -148,6 +150,22 @@ export const useWorkflowStore = defineStore('workflow-store', () => {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 停止工作流执行
|
||||
* @description 停止指定工作流的执行
|
||||
* @param {string} id - 工作流ID
|
||||
* @returns {Promise<void>} 停止执行结果
|
||||
*/
|
||||
const stopExistingWorkflow = async (id: string) => {
|
||||
try {
|
||||
const { message, fetch } = stopWorkflow({ id })
|
||||
message.value = true
|
||||
await fetch()
|
||||
} catch (error) {
|
||||
handleError(error).default($t('t_1_1747895712756'))
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取CA授权列表
|
||||
* @param {EabListParams} params - 请求参数
|
||||
@@ -217,6 +235,7 @@ export const useWorkflowStore = defineStore('workflow-store', () => {
|
||||
fetchWorkflowHistory,
|
||||
deleteExistingWorkflow,
|
||||
executeExistingWorkflow,
|
||||
stopExistingWorkflow,
|
||||
setWorkflowActive,
|
||||
setWorkflowExecType,
|
||||
fetchEabList,
|
||||
@@ -234,4 +253,4 @@ export const useWorkflowStore = defineStore('workflow-store', () => {
|
||||
export const useStore = () => {
|
||||
const store = useWorkflowStore()
|
||||
return { ...store, ...storeToRefs(store) }
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,15 @@
|
||||
// 外部库依赖
|
||||
import { Transition, type Component as ComponentType, h, defineComponent, ref, onMounted, computed, watch } from 'vue' // 添加 watch
|
||||
import {
|
||||
Transition,
|
||||
type Component as ComponentType,
|
||||
h,
|
||||
defineComponent,
|
||||
ref,
|
||||
onMounted,
|
||||
computed,
|
||||
watch,
|
||||
onUnmounted,
|
||||
} from 'vue' // 添加 watch, onUnmounted
|
||||
import { NBadge, NIcon, NLayout, NLayoutContent, NLayoutHeader, NLayoutSider, NMenu, NTooltip } from 'naive-ui'
|
||||
import { RouterView } from 'vue-router'
|
||||
import { MenuFoldOutlined, MenuUnfoldOutlined } from '@vicons/antd'
|
||||
@@ -12,7 +22,12 @@ import { useController } from './useController'
|
||||
import { $t } from '@locales/index'
|
||||
// 内部模块导入 - 样式
|
||||
import styles from './index.module.css'
|
||||
|
||||
// 内部模块导入 - API
|
||||
import { getVersion } from '@api/setting'
|
||||
// 内部模块导入 - 组件
|
||||
import UpdateLogModal from '@/components/UpdateLogModal'
|
||||
// 内部模块导入 - 类型
|
||||
import type { VersionData } from '@/types/setting'
|
||||
|
||||
/**
|
||||
* @description 基础布局组件,包含侧边栏导航、头部信息和内容区域。
|
||||
@@ -35,9 +50,39 @@ export default defineComponent({
|
||||
'actionColor',
|
||||
'layoutContentBackgroundColor',
|
||||
'siderLoginHeight', // 确保这个变量在 Naive UI 主题中存在或已自定义
|
||||
'contentPadding'
|
||||
'contentPadding',
|
||||
])
|
||||
|
||||
// 版本检查相关状态
|
||||
const hasUpdate = ref(false)
|
||||
const versionData = ref<VersionData | null>(null)
|
||||
const showUpdateModal = ref(false)
|
||||
const checkTimer = ref<NodeJS.Timeout | null>(null)
|
||||
|
||||
// 版本检查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)
|
||||
}
|
||||
}
|
||||
|
||||
// 点击版本号
|
||||
const handleVersionClick = () => {
|
||||
if (hasUpdate.value && versionData.value) {
|
||||
showUpdateModal.value = true
|
||||
}
|
||||
}
|
||||
|
||||
const siderWidth = ref(200)
|
||||
const siderCollapsedWidth = ref(60)
|
||||
|
||||
@@ -50,13 +95,28 @@ export default defineComponent({
|
||||
if (isMobile.value || isNarrowScreen.value) {
|
||||
isCollapsed.value = true
|
||||
}
|
||||
|
||||
// 初始检查版本
|
||||
checkVersion()
|
||||
|
||||
// 设置定时检查版本更新(每30分钟检查一次)
|
||||
checkTimer.value = setInterval(checkVersion, 30 * 60 * 1000)
|
||||
})
|
||||
|
||||
// 组件卸载时清理定时器
|
||||
onUnmounted(() => {
|
||||
if (checkTimer.value) {
|
||||
clearInterval(checkTimer.value)
|
||||
}
|
||||
})
|
||||
|
||||
// 监听屏幕宽度变化,自动折叠/展开菜单
|
||||
watch(isNarrowScreen, (newValue) => {
|
||||
if (newValue && !isMobile.value) { // 仅在非移动设备且宽度小于1100px时处理
|
||||
if (newValue && !isMobile.value) {
|
||||
// 仅在非移动设备且宽度小于1100px时处理
|
||||
isCollapsed.value = true
|
||||
} else if (!newValue && !isMobile.value) { // 宽度大于1100px且非移动设备时
|
||||
} else if (!newValue && !isMobile.value) {
|
||||
// 宽度大于1100px且非移动设备时
|
||||
isCollapsed.value = false
|
||||
}
|
||||
})
|
||||
@@ -109,13 +169,13 @@ export default defineComponent({
|
||||
class={[styles.sider, siderDynamicClass.value].join(' ')}
|
||||
bordered
|
||||
>
|
||||
<div class={`${styles.logoContainer} ${
|
||||
// Logo 容器的 'active' 状态 (仅在桌面端且折叠时应用)
|
||||
// 在移动端,由于 NLayoutSider 自身宽度不变,不应用 active 样式来改变 Logo 区域布局
|
||||
(isMobile.value ? false : isCollapsed.value)
|
||||
? styles.logoContainerActive
|
||||
: ''
|
||||
}`}>
|
||||
<div
|
||||
class={`${styles.logoContainer} ${
|
||||
// Logo 容器的 'active' 状态 (仅在桌面端且折叠时应用)
|
||||
// 在移动端,由于 NLayoutSider 自身宽度不变,不应用 active 样式来改变 Logo 区域布局
|
||||
(isMobile.value ? false : isCollapsed.value) ? styles.logoContainerActive : ''
|
||||
}`}
|
||||
>
|
||||
{/* Logo 显示逻辑 */}
|
||||
{(isMobile.value ? false : isCollapsed.value) ? (
|
||||
// 折叠时的 Logo (仅桌面端)
|
||||
@@ -134,11 +194,11 @@ export default defineComponent({
|
||||
<NTooltip placement="right" trigger="hover">
|
||||
{{
|
||||
trigger: () => (
|
||||
<div
|
||||
class={styles.menuToggleButton}
|
||||
onClick={() => toggleCollapse()}
|
||||
>
|
||||
<NIcon size={20}><MenuFoldOutlined /></NIcon> {/* 图标大小调整为 20 */}
|
||||
<div class={styles.menuToggleButton} onClick={() => toggleCollapse()}>
|
||||
<NIcon size={20}>
|
||||
<MenuFoldOutlined />
|
||||
</NIcon>{' '}
|
||||
{/* 图标大小调整为 20 */}
|
||||
</div>
|
||||
),
|
||||
default: () => <span>{$t('t_4_1744098802046')}</span>,
|
||||
@@ -172,9 +232,7 @@ export default defineComponent({
|
||||
{{
|
||||
trigger: () => (
|
||||
<div class={styles.headerMenuToggleButton} onClick={() => toggleCollapse()}>
|
||||
<NIcon size={20}>
|
||||
{isCollapsed.value ? <MenuUnfoldOutlined /> : <MenuFoldOutlined />}
|
||||
</NIcon>
|
||||
<NIcon size={20}>{isCollapsed.value ? <MenuUnfoldOutlined /> : <MenuFoldOutlined />}</NIcon>
|
||||
</div>
|
||||
),
|
||||
default: () => <span>展开主菜单</span>,
|
||||
@@ -183,8 +241,13 @@ export default defineComponent({
|
||||
</div>
|
||||
)}
|
||||
<div class={styles.systemInfo}>
|
||||
<NBadge value={1} show={false} dot>
|
||||
<span class="px-1 sm:px-[.5rem] cursor-pointer">v1.0.4</span>
|
||||
<NBadge value={1} show={hasUpdate.value} dot>
|
||||
<span
|
||||
class="px-[.8rem] sm:px-[.5rem] py-[.4rem] cursor-pointer hover:text-primary transition-colors text-[1.4rem] font-medium"
|
||||
onClick={handleVersionClick}
|
||||
>
|
||||
v1.0.4
|
||||
</span>
|
||||
</NBadge>
|
||||
</div>
|
||||
</NLayoutHeader>
|
||||
@@ -199,9 +262,10 @@ export default defineComponent({
|
||||
</NLayoutContent>
|
||||
</NLayout>
|
||||
{/* 移动端菜单展开时的背景遮罩 */}
|
||||
{showBackdrop.value && (
|
||||
<div class={styles.mobileMenuBackdrop} onClick={() => toggleCollapse()}></div>
|
||||
)}
|
||||
{showBackdrop.value && <div class={styles.mobileMenuBackdrop} onClick={() => toggleCollapse()}></div>}
|
||||
|
||||
{/* 更新日志弹窗 */}
|
||||
<UpdateLogModal v-model:show={showUpdateModal.value} versionData={versionData.value} />
|
||||
</NLayout>
|
||||
)
|
||||
},
|
||||
|
||||
@@ -14,7 +14,7 @@ import {
|
||||
useLoadingMask,
|
||||
} from '@baota/naive-ui/hooks'
|
||||
import { useError } from '@baota/hooks/error'
|
||||
import { isDomain } from '@baota/utils/business'
|
||||
import { isDomain, isPort, isIp } from '@baota/utils/business'
|
||||
import { $t } from '@locales/index'
|
||||
|
||||
// Store和组件
|
||||
@@ -64,6 +64,31 @@ const {
|
||||
// 错误处理
|
||||
const { handleError } = useError()
|
||||
|
||||
/**
|
||||
* 验证域名(或IP)+端口格式
|
||||
* @param value - 要验证的值
|
||||
* @returns {boolean} 如果是有效的域名、IP地址或它们加端口的格式,则返回 true
|
||||
*/
|
||||
const isDomainWithPort = (value: string): boolean => {
|
||||
if (!value) return false
|
||||
|
||||
// 检查是否包含端口号
|
||||
const parts = value.split(':')
|
||||
|
||||
if (parts.length === 1) {
|
||||
// 只有域名或IP,验证域名或IP地址
|
||||
return isDomain(value) || isIp(value)
|
||||
} else if (parts.length === 2) {
|
||||
// 域名/IP+端口格式
|
||||
const [host, port] = parts
|
||||
if (!host || !port) return false
|
||||
return (isDomain(host) || isIp(host)) && isPort(port)
|
||||
}
|
||||
|
||||
// 超过一个冒号,格式不正确(IPv6除外,但这里暂不处理IPv6+端口的复杂情况)
|
||||
return false
|
||||
}
|
||||
|
||||
/**
|
||||
* 监控管理业务逻辑控制器
|
||||
* @description 处理监控列表页面的业务逻辑,包括表格展示、添加、编辑、删除等操作
|
||||
@@ -318,7 +343,7 @@ export const useMonitorFormController = (data: UpdateSiteMonitorParams | null =
|
||||
*/
|
||||
const config = computed(() => [
|
||||
useFormInput('名称', 'name'),
|
||||
useFormInput('域名', 'domain'),
|
||||
useFormInput('域名/IP地址', 'domain'),
|
||||
useFormInputNumber('周期(分钟)', 'cycle', { class: 'w-full' }),
|
||||
useFormCustom(() => {
|
||||
return (
|
||||
@@ -342,11 +367,11 @@ export const useMonitorFormController = (data: UpdateSiteMonitorParams | null =
|
||||
name: { required: true, message: '请输入名称', trigger: 'input' },
|
||||
domain: {
|
||||
required: true,
|
||||
message: '请输入正确的域名',
|
||||
message: '请输入正确的域名或IP地址',
|
||||
trigger: 'input',
|
||||
validator: (rule: any, value: any, callback: any) => {
|
||||
if (!isDomain(value)) {
|
||||
callback(new Error('请输入正确的域名'))
|
||||
if (!isDomainWithPort(value)) {
|
||||
callback(new Error('请输入正确的域名或IP地址(支持域名:端口或IP:端口格式)'))
|
||||
} else {
|
||||
callback()
|
||||
}
|
||||
|
||||
@@ -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