【调整】监控页面整体优化

This commit is contained in:
chenzhihua
2025-07-17 11:04:36 +08:00
parent 624fc06f3e
commit 260601055f
81 changed files with 3316 additions and 925 deletions

View File

@@ -50,7 +50,7 @@ export const updateSiteMonitor = Mock.mock(/\/siteMonitor\/upd_site_monitor/, 'p
}))
// 删除站点监控
export const deleteSiteMonitor = Mock.mock(/\/siteMonitor\/del_site_monitor/, 'post', () => ({
export const deleteSiteMonitor = Mock.mock(/\/monitor\/del_monitor/, 'post', () => ({
code: 0,
count: 0,
data: null,

View File

@@ -3,9 +3,16 @@ import type { useAxiosReturn } from '@baota/hooks/axios'
import type {
AddSiteMonitorParams,
DeleteSiteMonitorParams,
FileImportMonitorParams,
FileImportMonitorResponse,
GetErrorRecordParams,
GetErrorRecordResponse,
GetMonitorDetailParams,
GetMonitorDetailResponse,
SetSiteMonitorParams,
SiteMonitorListParams,
SiteMonitorListResponse,
TemplateDownloadParams,
UpdateSiteMonitorParams,
} from '@/types/monitor' // Sorted types
import type { AxiosResponseData } from '@/types/public'
@@ -21,15 +28,17 @@ import { useApi } from '@api/index'
export const getSiteMonitorList = (
params?: SiteMonitorListParams,
): useAxiosReturn<SiteMonitorListResponse, SiteMonitorListParams> =>
useApi<SiteMonitorListResponse, SiteMonitorListParams>('/v1/siteMonitor/get_list', params)
useApi<SiteMonitorListResponse, SiteMonitorListParams>('/v1/monitor/get_list', params)
/**
* @description 新增站点监控
* @param {AddSiteMonitorParams} [params] 请求参数
* @returns {useAxiosReturn<AxiosResponseData, AddSiteMonitorParams>} 新增站点监控的组合式 API 调用封装。包含响应数据、加载状态及执行函数。
*/
export const addSiteMonitor = (params?: AddSiteMonitorParams): useAxiosReturn<AxiosResponseData, AddSiteMonitorParams> =>
useApi<AxiosResponseData, AddSiteMonitorParams>('/v1/siteMonitor/add_site_monitor', params)
export const addSiteMonitor = (
params?: AddSiteMonitorParams,
): useAxiosReturn<AxiosResponseData, AddSiteMonitorParams> =>
useApi<AxiosResponseData, AddSiteMonitorParams>('/v1/monitor/add_monitor', params)
/**
* @description 修改站点监控
@@ -39,7 +48,7 @@ export const addSiteMonitor = (params?: AddSiteMonitorParams): useAxiosReturn<Ax
export const updateSiteMonitor = (
params?: UpdateSiteMonitorParams,
): useAxiosReturn<AxiosResponseData, UpdateSiteMonitorParams> =>
useApi<AxiosResponseData, UpdateSiteMonitorParams>('/v1/siteMonitor/upd_site_monitor', params)
useApi<AxiosResponseData, UpdateSiteMonitorParams>('/v1/monitor/upd_monitor', params)
/**
* @description 删除站点监控
@@ -49,12 +58,61 @@ export const updateSiteMonitor = (
export const deleteSiteMonitor = (
params?: DeleteSiteMonitorParams,
): useAxiosReturn<AxiosResponseData, DeleteSiteMonitorParams> =>
useApi<AxiosResponseData, DeleteSiteMonitorParams>('/v1/siteMonitor/del_site_monitor', params)
useApi<AxiosResponseData, DeleteSiteMonitorParams>('/v1/monitor/del_monitor', params)
/**
* @description 启用/禁用站点监控
* @param {SetSiteMonitorParams} [params] 请求参数
* @returns {useAxiosReturn<AxiosResponseData, SetSiteMonitorParams>} 启用/禁用站点监控的组合式 API 调用封装。包含响应数据、加载状态及执行函数。
*/
export const setSiteMonitor = (params?: SetSiteMonitorParams): useAxiosReturn<AxiosResponseData, SetSiteMonitorParams> =>
useApi<AxiosResponseData, SetSiteMonitorParams>('/v1/siteMonitor/set_site_monitor', params)
export const setSiteMonitor = (
params?: SetSiteMonitorParams,
): useAxiosReturn<AxiosResponseData, SetSiteMonitorParams> =>
useApi<AxiosResponseData, SetSiteMonitorParams>('/v1/monitor/set_monitor', params)
/**
* @description 获取监控详情信息
* @param {GetMonitorDetailParams} [params] 请求参数
* @returns {useAxiosReturn<GetMonitorDetailResponse, GetMonitorDetailParams>} 获取监控详情信息的组合式 API 调用封装。包含响应数据、加载状态及执行函数。
*/
export const getMonitorDetail = (
params?: GetMonitorDetailParams,
): useAxiosReturn<GetMonitorDetailResponse, GetMonitorDetailParams> =>
useApi<GetMonitorDetailResponse, GetMonitorDetailParams>('/v1/monitor/get_monitor_info', params)
/**
* @description 获取监控错误记录
* @param {GetErrorRecordParams} [params] 请求参数
* @returns {useAxiosReturn<GetErrorRecordResponse, GetErrorRecordParams>} 获取监控错误记录的组合式 API 调用封装。包含响应数据、加载状态及执行函数。
*/
export const getMonitorErrorRecord = (
params?: GetErrorRecordParams,
): useAxiosReturn<GetErrorRecordResponse, GetErrorRecordParams> =>
useApi<GetErrorRecordResponse, GetErrorRecordParams>('/v1/monitor/get_err_record', params)
/**
* @description 文件导入监控
* @param {FileImportMonitorParams} [params] 请求参数
* @returns {useAxiosReturn<FileImportMonitorResponse, FileImportMonitorParams>} 文件导入监控的组合式 API 调用封装。包含响应数据、加载状态及执行函数。
*/
export const fileImportMonitor = (
params?: FileImportMonitorParams,
): useAxiosReturn<FileImportMonitorResponse, FileImportMonitorParams> =>
useApi<FileImportMonitorResponse, FileImportMonitorParams>('/v1/monitor/file_add_monitor', params)
/**
* @description 下载监控模板
* @param {TemplateDownloadParams} params 请求参数
* @returns {Promise<Blob>} 返回模板文件的Blob对象
*/
export const downloadMonitorTemplate = async (params: TemplateDownloadParams): Promise<Blob> => {
const response = await fetch(`/v1/monitor/template?type=${params.type}`, {
method: 'GET',
})
if (!response.ok) {
throw new Error(`下载模板失败: ${response.statusText}`)
}
return response.blob()
}

View File

@@ -0,0 +1,126 @@
/* 通知提供商多选组件样式 */
/* 主容器样式 */
.notifyProviderMultiSelect {
width: 100%;
}
/* 选择器容器样式 - 确保有足够空间显示多选标签 */
.selectContainer {
width: 100%;
min-height: 2.5rem;
}
/* 修复 NSelect 输入框区域的垂直对齐问题 */
.selectContainer :global(.n-base-selection) {
align-items: center !important;
min-height: 2.5rem !important;
}
/* 修复选择器输入框内容区域对齐 */
.selectContainer :global(.n-base-selection-input) {
display: flex !important;
align-items: center !important;
min-height: 2.5rem !important;
}
/* 修复标签容器的垂直对齐 */
.selectContainer :global(.n-base-selection-tags) {
display: flex;
flex-wrap: wrap;
gap: 0.25rem;
min-height: 2.5rem;
padding: 0.25rem;
max-height: none !important; /* 移除高度限制,允许换行 */
align-items: center !important;
align-content: center !important;
}
/* 修复下拉箭头的垂直对齐 */
.selectContainer :global(.n-base-suffix) {
display: flex !important;
align-items: center !important;
height: 100% !important;
}
/* 修复清除按钮的垂直对齐 */
.selectContainer :global(.n-base-clear) {
display: flex !important;
align-items: center !important;
height: 100% !important;
}
/* 修复输入框整体的垂直对齐 */
.selectContainer :global(.n-base-selection-input-tag) {
display: flex !important;
align-items: center !important;
min-height: 2.5rem !important;
}
/* 确保占位符文本垂直居中 */
.selectContainer :global(.n-base-selection-placeholder) {
display: flex !important;
align-items: center !important;
line-height: 2.5rem !important;
}
/* 修复多选模式下的输入框对齐 */
.selectContainer :global(.n-base-selection-input-tag input) {
line-height: 2.5rem !important;
height: 2.5rem !important;
}
/* 标签样式优化 */
.selectContainer :global(.n-tag) {
max-width: 100%;
flex-shrink: 0;
margin: 2px 4px 2px 0 !important;
display: flex !important;
align-items: center !important;
}
/* 标签内容样式 */
.selectContainer :global(.n-tag__content) {
display: flex !important;
align-items: center !important;
gap: 0.25rem;
max-width: 100%;
}
/* 响应式布局 - 保持按钮原始样式 */
/* 确保选择器在不同屏幕尺寸下的响应式表现 */
@media (max-width: 640px) {
.selectContainer {
min-height: 3rem;
}
.selectContainer :global(.n-base-selection-tags) {
min-height: 3rem;
}
}
/* 优化标签在小屏幕上的显示 */
@media (max-width: 480px) {
.selectContainer :global(.n-tag) {
font-size: 0.75rem;
max-width: 150px;
}
.selectContainer :global(.n-tag__content) {
gap: 0.125rem;
}
}
/* 确保图标不会被压缩 */
.selectContainer :global(.svg-icon) {
flex-shrink: 0;
}
/* 优化空状态显示 */
.emptyState {
text-align: center;
padding: 1rem 0;
}
/* 保持按钮原始样式,不做额外修改 */

View File

@@ -0,0 +1,229 @@
// External Libraries
import { defineComponent, computed } from 'vue'
import { NButton, NDivider, NFlex, NFormItemGi, NGi, NGrid, NSelect, NText, NCheckboxGroup, NCheckbox } from 'naive-ui'
// Type Imports
import type { VNode, PropType } from 'vue'
import type { SelectOption } from 'naive-ui'
import type { NotifyProviderOption, NotifyProviderMultiSelectProps } from './types'
// Absolute Internal Imports - Components
import SvgIcon from '@components/SvgIcon'
// Absolute Internal Imports - Utilities / Others
import { $t } from '@locales/index'
// Relative Internal Imports - Controller
import { useNotifyProviderMultiSelectController } from './useController'
// Relative Internal Imports - Styles
import styles from './index.module.css'
/**
* @description 通知提供商多选组件。允许用户从列表中选择多个通知渠道。
* @example
* <NotifyProviderMultiSelect
* path="form.channels"
* v-model:value="selectedChannelValues"
* valueType="type"
* :isAddMode="true"
* @update:value="(options) => handleChannelsChange(options)"
* />
*/
export default defineComponent({
name: 'NotifyProviderMultiSelect',
props: {
/**
* 表单项的路径,用于表单校验或上下文。
* @default ''
*/
path: {
type: String as PropType<NotifyProviderMultiSelectProps['path']>,
default: '',
},
/**
* 当前选中的值数组 (对应 NotifyProviderOption['value'][] 数组)。
* @default []
*/
value: {
type: Array as PropType<NotifyProviderMultiSelectProps['value']>,
default: () => [],
},
/**
* 决定 `props.value` 和 `NotifyProviderOption.value` 字段是基于原始提供商的 `value` 还是 `type`。
* - 'value': 使用原始提供商的 `value` 字段作为 `NotifyProviderOption.value`。
* - 'type': 使用原始提供商的 `type` 字段作为 `NotifyProviderOption.value`。
* @default 'value'
*/
valueType: {
type: String as PropType<NotifyProviderMultiSelectProps['valueType']>,
default: 'value',
validator: (val: string) => ['value', 'type'].includes(val),
},
/**
* 是否为添加模式,显示额外的"新增渠道"和"刷新"按钮。
* @default false
*/
isAddMode: {
type: Boolean as PropType<NotifyProviderMultiSelectProps['isAddMode']>,
default: false,
},
/**
* 最大选择数量限制。
* @default undefined
*/
maxCount: {
type: Number as PropType<NotifyProviderMultiSelectProps['maxCount']>,
default: undefined,
},
/**
* 是否禁用。
* @default false
*/
disabled: {
type: Boolean as PropType<NotifyProviderMultiSelectProps['disabled']>,
default: false,
},
},
/**
* @event update:value - 当选中的通知提供商更新时触发。
* @param {NotifyProviderOption[]} options - 选中的通知提供商的完整对象数组。
*/
emits: {
'update:value': (payload: NotifyProviderOption[]) => {
return (
Array.isArray(payload) &&
payload.every(
(item) => typeof item === 'object' && item !== null && 'label' in item && 'value' in item && 'type' in item,
)
)
},
},
setup(props: NotifyProviderMultiSelectProps, { emit }) {
const { selectOptions, goToAddNotifyProvider, handleMultiSelectUpdate, fetchNotifyProviderData } =
useNotifyProviderMultiSelectController(props, emit)
/**
* @description 渲染多选标签 (Tag)。
* @param {object} params - Naive UI 传递的选项包装对象。
* @param {SelectOption} params.option - 当前选项的数据。
* @returns {VNode} 渲染后的 VNode。
*/
const renderMultiSelectTag = ({ option }: { option: SelectOption }): VNode => {
// 将 SelectOption 转换为 NotifyProviderOption
const notifyOption = option as NotifyProviderOption & SelectOption
// 处理长标签文本的截断
const truncateText = (text: string, maxLength: number = 20): string => {
if (text.length <= maxLength) return text
return text.slice(0, maxLength) + '...'
}
return (
<div class="flex items-center max-w-full h-full">
{notifyOption.label ? (
<NFlex align="center" justify="center" size="small" class="min-w-0 flex-1 h-full">
<SvgIcon icon={`notify-${notifyOption.type || ''}`} size="1.4rem" class="flex-shrink-0" />
<span
class="text-[12px] truncate min-w-0 block"
title={notifyOption.label}
style={{
maxWidth: '120px',
lineHeight: '1.5',
display: 'flex',
alignItems: 'center',
}}
>
{truncateText(notifyOption.label)}
</span>
</NFlex>
) : (
<NText depth="3" class="text-[12px] flex items-center h-full">
{$t('t_0_1745887835267')}
</NText>
)}
</div>
)
}
/**
* @description 渲染下拉列表中的选项标签。
* @param {SelectOption} option - 当前选项的数据。
* @returns {VNode} 渲染后的 VNode。
*/
const renderLabel = (option: SelectOption): VNode => {
// 将 SelectOption 转换为 NotifyProviderOption
const notifyOption = option as NotifyProviderOption & SelectOption
return (
<NFlex align="center" size="small">
<SvgIcon icon={`notify-${notifyOption.type || ''}`} size="1.6rem" />
<NText>{notifyOption.label}</NText>
</NFlex>
)
}
// 转换选项格式以兼容 NSelect
const naiveSelectOptions = computed(() => {
return selectOptions.value.map((option): SelectOption & NotifyProviderOption => ({
...option,
// 确保兼容 NSelect 的 SelectOption 接口
}))
})
return () => (
<div class={styles.notifyProviderMultiSelect}>
<NGrid cols={24}>
<NFormItemGi
span={props.isAddMode ? 13 : 24}
label={$t('t_1_1745887832941') /* 通知渠道 */}
path={props.path}
>
<div class={styles.selectContainer}>
<NSelect
class="w-full"
style={{
'--n-tag-text-color': 'var(--n-text-color)',
'--n-tag-border-radius': '6px',
'min-height': '2.5rem',
'--n-height': '2.5rem',
'--n-height-medium': '2.5rem',
}}
options={naiveSelectOptions.value}
renderLabel={renderLabel}
renderTag={renderMultiSelectTag}
filterable
clearable
multiple
maxTagCount="responsive"
placeholder={$t('t_0_1745887835267')}
value={props.value} // 直接使用 props.value 数组
onUpdateValue={handleMultiSelectUpdate}
disabled={props.disabled}
v-slots={{
empty: () => (
<div class={styles.emptyState}>
<NText depth="3" class="text-[1.4rem]">
{selectOptions.value.length === 0 ? $t('t_0_1745887835267') : '暂无匹配的通知渠道'}
</NText>
</div>
),
}}
/>
</div>
</NFormItemGi>
{props.isAddMode && (
<NGi span={11}>
<div class="flex items-center h-full">
<NDivider vertical />
<NButton class="mx-[8px]" onClick={goToAddNotifyProvider} ghost>
{$t('t_2_1745887834248')}
</NButton>
<NButton onClick={fetchNotifyProviderData} ghost>
{$t('t_0_1746497662220')}
</NButton>
</div>
</NGi>
)}
</NGrid>
</div>
)
},
})

View File

@@ -0,0 +1,111 @@
// Type Imports
import type { Ref } from 'vue'
/**
* @description 通知提供商选项的类型定义
*/
export interface NotifyProviderOption {
/**
* 选项的显示标签
*/
label: string
/**
* 选项的实际值 (用于多选的 v-model)
*/
value: string
/**
* 选项的原始类型 (例如 'email', 'sms'), 用于图标显示等业务逻辑
*/
type: string
}
/**
* @description 从 Store 获取的原始通知提供商项目类型
*/
export interface RawProviderItem {
/**
* 显示标签
*/
label: string
/**
* 实际值
*/
value: string
/**
* 原始类型
*/
type: string
/**
* 允许其他可能的属性
*/
[key: string]: any
}
/**
* @description NotifyProviderMultiSelect 组件的 Props 定义
*/
export interface NotifyProviderMultiSelectProps {
/**
* 表单项的路径,用于表单校验或上下文
* @default ''
*/
path: string
/**
* 当前选中的值数组 (对应 NotifyProviderOption['value'][])
* @default []
*/
value: string[]
/**
* 决定 `props.value` 和 `NotifyProviderOption.value` 字段是基于原始提供商的 `value` 还是 `type`
* - 'value': 使用原始提供商的 `value` 字段作为 `NotifyProviderOption.value`
* - 'type': 使用原始提供商的 `type` 字段作为 `NotifyProviderOption.value`
* @default 'value'
*/
valueType: 'value' | 'type'
/**
* 是否为添加模式,显示额外的按钮
* @default false
*/
isAddMode: boolean
/**
* 最大选择数量限制
* @default undefined
*/
maxCount?: number
/**
* 是否禁用
* @default false
*/
disabled?: boolean
}
/**
* @description NotifyProviderMultiSelect 组件的 Emits 定义
*/
export interface NotifyProviderMultiSelectEmits {
(e: 'update:value', payload: NotifyProviderOption[]): void
}
// Controller暴露给View的类型
export interface NotifyProviderMultiSelectControllerExposes {
/**
* 内部选中的完整通知提供商对象数组
*/
selectedOptionsFull: Ref<NotifyProviderOption[]>
/**
* 格式化后用于多选组件的选项列表
*/
selectOptions: Ref<NotifyProviderOption[]>
/**
* 打开通知渠道配置页面的方法
*/
goToAddNotifyProvider: () => void
/**
* 处理多选值更新的方法
*/
handleMultiSelectUpdate: (values: string[]) => void
/**
* 手动刷新通知提供商列表的方法
*/
fetchNotifyProviderData: () => void
}

View File

@@ -0,0 +1,155 @@
// External Libraries
import { ref, watch, computed } from 'vue'
// Type Imports
import type {
NotifyProviderOption,
NotifyProviderMultiSelectControllerExposes,
NotifyProviderMultiSelectProps,
RawProviderItem,
} from './types'
// Absolute Internal Imports - Store
import { useStore } from '@layout/useStore'
// Absolute Internal Imports - Config
import { MessagePushConfig } from '@config/data'
/**
* @description NotifyProviderMultiSelect 组件的控制器逻辑
* @param props - 组件的 props
* @param emit - 组件的 emit 函数
* @returns {NotifyProviderMultiSelectControllerExposes} 暴露给视图的响应式数据和方法
*/
export function useNotifyProviderMultiSelectController(
props: NotifyProviderMultiSelectProps,
emit: (event: 'update:value', payload: NotifyProviderOption[]) => void,
): NotifyProviderMultiSelectControllerExposes {
const { fetchNotifyProvider, notifyProvider } = useStore()
// 内部存储当前选中的完整 NotifyProviderOption 对象数组
const selectedOptionsFull = ref<NotifyProviderOption[]>([])
// 存储多选组件使用的选项列表
const selectOptions = ref<NotifyProviderOption[]>([])
/**
* @description 从 MessagePushConfig 生成备用选项列表
*/
const fallbackOptions = computed<NotifyProviderOption[]>(() => {
return Object.entries(MessagePushConfig).map(([key, config]) => ({
label: config.name,
value: props.valueType === 'value' ? key : config.type,
type: config.type,
}))
})
/**
* @description 根据当前选中的值数组更新内部完整选中项数组
* @param currentSelectedValues - 当前选中的值数组 (字符串数组)
*/
const updateInternalSelectedOptions = (currentSelectedValues: string[]): void => {
if (!currentSelectedValues || currentSelectedValues.length === 0) {
selectedOptionsFull.value = []
return
}
const newSelectedOptions: NotifyProviderOption[] = []
currentSelectedValues.forEach((value) => {
// 首先尝试从当前选项列表中查找
let foundOption = selectOptions.value.find((option) => option.value === value)
if (!foundOption) {
// 如果在当前选项列表中找不到,尝试从备用选项中查找
foundOption = fallbackOptions.value.find((option) => option.value === value)
}
if (foundOption) {
newSelectedOptions.push({ ...foundOption })
} else {
// 如果都找不到,创建一个临时选项
newSelectedOptions.push({
label: value,
value: value,
type: '',
})
}
})
selectedOptionsFull.value = newSelectedOptions
}
/**
* @description 打开通知渠道配置页面
*/
const goToAddNotifyProvider = (): void => {
window.open('/settings?tab=notification', '_blank')
}
/**
* @description 处理多选组件的值更新事件
* @param newSelectedValues - 多选组件更新的 modelValue (字符串数组)
*/
const handleMultiSelectUpdate = (newSelectedValues: string[]): void => {
updateInternalSelectedOptions(newSelectedValues)
emit('update:value', [...selectedOptionsFull.value]) // Emit a copy of the array
}
/**
* @description 外部调用以刷新通知提供商列表
*/
const fetchNotifyProviderData = (): void => {
fetchNotifyProvider()
}
// 监听父组件传入的 props.value (可能是初始值或外部更改)
watch(
() => props.value,
(newVal) => {
// 确保提供商列表已加载或正在加载,然后再尝试更新选中项细节
if (selectOptions.value.length === 0 && newVal && newVal.length > 0) {
fetchNotifyProviderData() // 如果列表为空且有 props.value触发加载
}
updateInternalSelectedOptions(newVal)
},
{ immediate: true, deep: true },
)
// 监听从 Store 获取的原始通知提供商列表,并进行转换
watch(
() => notifyProvider.value,
(rawProviders) => {
if (rawProviders && rawProviders.length > 0) {
// 如果 Store 中有数据,使用 Store 数据
selectOptions.value = rawProviders.map((item: RawProviderItem) => ({
label: item.label,
// `value` 字段给多选组件使用,根据 props.valueType 决定其来源
value: props.valueType === 'value' ? item.value : item.type,
// `type` 字段始终为原始提供商的 type用于 SvgIcon
type: item.type,
}))
} else {
// 如果 Store 中没有数据,使用备用数据源
selectOptions.value = fallbackOptions.value
}
// Store 数据更新后,基于当前 props.value 重新更新内部完整选中项
updateInternalSelectedOptions(props.value)
},
{ immediate: true, deep: true },
)
// 初始化时如果 Store 为空,先使用备用数据
if (!notifyProvider.value || notifyProvider.value.length === 0) {
selectOptions.value = fallbackOptions.value
// 尝试获取 Store 数据
fetchNotifyProviderData()
}
return {
selectedOptionsFull,
selectOptions,
goToAddNotifyProvider,
handleMultiSelectUpdate,
fetchNotifyProviderData,
}
}

View File

@@ -1,5 +1,5 @@
import { defineComponent, PropType } from 'vue'
import { NTag } from 'naive-ui'
import { NTag, NFlex } from 'naive-ui'
// 类型导入
import type { AuthApiTypeIconProps } from './types'
@@ -24,11 +24,11 @@ export default defineComponent({
name: 'AuthApiTypeIcon',
props: {
/**
* 图标类型键。
* 图标类型键。支持单个字符串或字符串数组。
* 该键用于从 /lib/data.tsx 配置中查找对应的图标和名称。
*/
icon: {
type: String as PropType<AuthApiTypeIconProps['icon']>,
type: [String, Array] as PropType<AuthApiTypeIconProps['icon']>,
required: true,
},
/**
@@ -47,17 +47,41 @@ export default defineComponent({
},
},
setup(props: AuthApiTypeIconProps) {
const { iconPath, typeName } = useAuthApiTypeIconController(props)
const { iconPath, typeName, iconItems } = useAuthApiTypeIconController(props)
return () => (
<NTag
type={props.type}
size="small"
class="w-auto text-ellipsis overflow-hidden whitespace-normal p-[.6rem] h-auto"
>
<SvgIcon icon={iconPath.value} size="1.2rem" class="mr-[0.4rem]" />
<span>{props.text && <span class="text-[12px]">{typeName.value}</span>}</span>
</NTag>
)
return () => {
// 如果是多个图标,显示多个标签
if (Array.isArray(props.icon) && props.icon.length > 1) {
return (
<NFlex size="small" wrap={true} style="gap: 4px; flex-wrap: wrap;">
{iconItems.value.map((item, index) => (
<NTag
key={item.key}
type={props.type}
size="small"
class="w-auto text-ellipsis overflow-hidden whitespace-normal p-[.6rem] h-auto mb-1"
style="margin-right: 4px; max-width: 100%;"
>
<SvgIcon icon={item.iconPath} size="1.2rem" class="mr-[0.4rem] flex-shrink-0" />
{props.text && <span class="text-[12px] truncate">{item.typeName}</span>}
</NTag>
))}
</NFlex>
)
}
// 单个图标的显示(包括数组只有一个元素的情况)
return (
<NTag
type={props.type}
size="small"
class="w-auto text-ellipsis overflow-hidden whitespace-normal p-[.6rem] h-auto"
style="max-width: 100%;"
>
<SvgIcon icon={iconPath.value} size="1.2rem" class="mr-[0.4rem] flex-shrink-0" />
{props.text && <span class="text-[12px] truncate">{typeName.value}</span>}
</NTag>
)
}
},
})

View File

@@ -3,11 +3,12 @@
*/
export interface AuthApiTypeIconProps {
/**
* 图标类型键。
* 图标类型键。支持单个字符串或字符串数组。
* 该键用于从 /lib/data.tsx 配置中查找对应的图标和名称。
* 如果未在配置中找到,将尝试使用 'default' 图标,并直接显示该键作为文本。
* 当传入数组时,会显示多个图标标签。
*/
icon: string
icon: string | string[]
/**
* NTag 的类型。
* @default 'default'
@@ -20,6 +21,15 @@ export interface AuthApiTypeIconProps {
text?: boolean
}
/**
* 图标项的类型定义
*/
export interface IconItem {
iconPath: string
typeName: string
key: string
}
/**
* useAuthApiTypeIconController Composable 函数暴露的接口。
*/
@@ -28,6 +38,8 @@ export interface AuthApiTypeIconControllerExposes {
iconPath: globalThis.ComputedRef<string>
/** 计算得到的类型名称,用于显示 */
typeName: globalThis.ComputedRef<string>
/** 计算得到的所有图标项,用于多图标显示 */
iconItems: globalThis.ComputedRef<IconItem[]>
}
/**

View File

@@ -53,34 +53,65 @@ if (ApiProjectConfig.btwaf) {
/**
* @function useAuthApiTypeIconController
* @description AuthApiTypeIcon 组件的控制器逻辑。
* @description AuthApiTypeIcon 组件的控制器逻辑,支持单个或多个图标
* @param props - 组件的 props。
* @returns {AuthApiTypeIconControllerExposes} 控制器暴露给视图的数据和方法。
*/
export function useAuthApiTypeIconController(props: AuthApiTypeIconProps): AuthApiTypeIconControllerExposes {
/**
* @computed iconPath
* @description 根据 props.icon 计算 SvgIcon 所需的图标名称。
* @description 根据 props.icon 计算 SvgIcon 所需的图标名称。支持单个或多个图标。
*/
const iconPath = computed<string>(() => {
const isNotify = notifyKeys.has(props.icon)
// 如果是数组,取第一个作为主要图标
const iconKey = Array.isArray(props.icon) ? props.icon[0] : props.icon
if (!iconKey) return 'resources-default'
const isNotify = notifyKeys.has(iconKey)
const RESOURCE_PREFIX = isNotify ? 'notify-' : 'resources-'
// 从映射表中获取图标文件名,如果找不到则使用 'default'
const iconStem = iconFileMap[props.icon] || 'default'
const iconStem = iconFileMap[iconKey] || 'default'
return RESOURCE_PREFIX + iconStem
})
/**
* @computed typeName
* @description 根据 props.icon 获取对应的显示名称。
* @description 根据 props.icon 获取对应的显示名称。支持单个或多个名称。
*/
const typeName = computed<string>(() => {
// 从映射表中获取显示名称,如果找不到则直接使用 props.icon
return typeNamesMap[props.icon] || props.icon
if (Array.isArray(props.icon)) {
// 如果是数组,组合多个名称
return props.icon
.filter(Boolean)
.map((iconKey) => typeNamesMap[iconKey] || iconKey)
.join(', ')
} else {
// 单个图标的处理
return typeNamesMap[props.icon] || props.icon
}
})
/**
* @computed iconItems
* @description 计算所有图标项,用于多图标显示
*/
const iconItems = computed(() => {
const icons = Array.isArray(props.icon) ? props.icon : [props.icon]
return icons.filter(Boolean).map((iconKey) => {
const isNotify = notifyKeys.has(iconKey)
const RESOURCE_PREFIX = isNotify ? 'notify-' : 'resources-'
const iconStem = iconFileMap[iconKey] || 'default'
return {
iconPath: RESOURCE_PREFIX + iconStem,
typeName: typeNamesMap[iconKey] || iconKey,
key: iconKey,
}
})
})
return {
iconPath,
typeName,
iconItems,
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -4,6 +4,7 @@ import useRouterEach from './each' // 全局路由守卫
// 获取路由
const { routeGroup, routes } = createRoutes() // 获取路由配置
console.log(routeGroup, routes)
// 创建路由
const router = useCreateRouter({

View File

@@ -44,6 +44,9 @@
background-color: var(--n-merged-td-color);
}
.n-scrollbar > .n-scrollbar-rail.n-scrollbar-rail--horizontal--top, .n-scrollbar + .n-scrollbar-rail.n-scrollbar-rail--horizontal--top {
top: 40px !important;
}
.leftPanel .n-tabs-tab {
height: 3.2rem;

View File

@@ -109,7 +109,8 @@ type SshAccessConfig = {
host: string
port: number
user: string
} & ({ mode: 'password'; password: string; key?: never } | { mode: 'key'; key: string; password?: never })
password?: string // 密码字段:密码模式下作为登录密码,密钥模式下作为私钥密码(可选)
} & ({ mode: 'password'; key?: never } | { mode: 'key'; key: string })
/**
* 阿里云授权配置

View File

@@ -9,21 +9,26 @@ export interface SiteMonitorListParams {
/** 站点监控项 */
export interface SiteMonitorItem {
active: number
ca: string
cert_domain: string
create_time: string
cycle: number
end_day: string
end_time: string
except_end_time: string
id: number
last_time: string
name: string
report_type: string
site_domain: string
state: string
update_time: string
active: number // Monitor active status (1 = active, 0 = inactive)
advance_day: number // Days in advance for notification
ca: string // Certificate Authority (e.g., "sslTrus")
common_name: string // Certificate common name (e.g., "*.bt.cn")
create_time: string // Creation timestamp (YYYY-MM-DD HH:mm:ss)
cycle: number // Monitoring cycle
days_left: number // Days remaining until expiration
except_end_time: string // Expected end time (YYYY-MM-DD HH:mm:ss)
id: number // Unique identifier
last_time: string // Last check time (YYYY-MM-DD HH:mm:ss)
monitor_type: string // Type of monitoring (e.g., "https")
name: string // Monitor name
not_after: string // Certificate valid until (YYYY-MM-DD HH:mm:ss)
not_before: string // Certificate valid from (YYYY-MM-DD HH:mm:ss)
repeat_send_gap: number | null // Gap between repeat notifications
report_types: string | string[] // Notification types (e.g., "dingtalk" or ["dingtalk", "mail"])
sans: string // Subject Alternative Names
target: string // Monitoring target URL/domain
update_time: string // Last update time (YYYY-MM-DD HH:mm:ss)
valid: number // Certificate validity status (1 = valid, 0 = invalid)
}
/** 站点监控列表响应 */
@@ -34,9 +39,13 @@ export interface SiteMonitorListResponse extends AxiosResponseData {
/** 新增站点监控请求参数 */
export interface AddSiteMonitorParams {
name: string
domain: string
target: string
monitor_type: string // 监控类型 (e.g., "https", "smtp")
report_types: string | string[] // 支持单个或多个通知类型
cycle: number
report_type: string
repeat_send_gap: number // 重复发送间隔(次数)
active: number // 启用状态 (1 = 启用, 0 = 禁用)
advance_day: number // 提前天数
}
/** 修改站点监控请求参数 */
@@ -53,3 +62,92 @@ export interface SetSiteMonitorParams {
id: number
active: number
}
/** 证书链节点信息 */
export interface CertChainNode {
common_name: string // 通用名称
subject: string // 主题信息
issuer: string // 颁发者信息
children?: CertChainNode[] // 子证书链节点
}
/** 监控详情信息 */
export interface MonitorDetailInfo {
ca: string // 证书颁发机构
cert_chain: CertChainNode // 证书链信息
common_name: string // 通用名称
days_left: number // 剩余天数
err_count: number // 错误次数
last_time: string // 上次检测时间 (YYYY-MM-DD HH:mm:ss)
monitor_type: string // 监控类型
name: string // 监控名称
not_after: string // 证书到期时间
not_before: string // 证书生效时间
sans: string // 主题备用名称
target: string // 监控目标
tls_version?: string // 支持的TLS版本可选字段
valid: number // 验证状态 (1=有效, 0=无效)
verify_error: string // 验证错误信息
}
/** 获取监控详情请求参数 */
export interface GetMonitorDetailParams {
id: number
}
/** 获取监控详情响应 */
export interface GetMonitorDetailResponse extends AxiosResponseData {
data: MonitorDetailInfo
}
/** 错误记录项 */
export interface ErrorRecord {
create_time: string // 创建时间 (YYYY-MM-DD HH:mm:ss)
id: number // 记录ID
info: string // 附加信息
monitor_id: number // 监控ID
msg: string // 错误消息内容
}
/** 获取错误记录请求参数 */
export interface GetErrorRecordParams {
id: number // 监控ID
p: number // 页码
limit: number // 每页条数
}
/** 获取错误记录响应 */
export interface GetErrorRecordResponse extends AxiosResponseData {
count: number // 总记录数
data: ErrorRecord[] // 错误记录数组
}
/** 文件导入监控请求参数 */
export interface FileImportMonitorParams {
file: File // 上传的文件
}
/** 文件导入监控响应 */
export interface FileImportMonitorResponse extends AxiosResponseData {
data: {
success_count: number // 成功导入数量
failed_count: number // 失败导入数量
failed_items?: string[] // 失败的项目列表(可选)
}
}
/** 模板下载请求参数 */
export interface TemplateDownloadParams {
type: 'txt' | 'csv' | 'json' | 'xlsx' // 模板类型
}
/** 支持的文件格式类型 */
export type SupportedFileType = 'txt' | 'csv' | 'json' | 'xlsx'
/** 文件上传状态 */
export interface FileUploadStatus {
uploading: boolean
progress: number
error?: string
success?: boolean
}

View File

@@ -363,10 +363,20 @@ export const useApiFormController = (props: ApiFormControllerProps): ApiFormCont
password: {
trigger: 'input',
validator: (rule: FormItemRule, value: string, callback: (error?: Error) => void) => {
// SSH 类型的密码字段在密码模式下是必填的,在密钥模式下是可选的
if (param.value.type === 'ssh') {
const sshConfig = param.value.config as SshAccessConfig
if (sshConfig?.mode === 'password' && !value) {
return callback(new Error($t('t_0_1747711335067')))
}
// 密钥模式下密码是可选的,不需要验证
callback()
return
}
if (!value) {
const mapTips = {
westcn: $t('t_1_1747365603108'),
ssh: $t('t_0_1747711335067'),
lecdn: '请输入密码',
}
return callback(new Error(mapTips[param.value.type as keyof typeof mapTips]))
@@ -593,8 +603,9 @@ export const useApiFormController = (props: ApiFormControllerProps): ApiFormCont
// 根据不同类型渲染不同的表单项
switch (param.value.type) {
case 'ssh':
items.push(
case 'ssh': {
// SSH 基础配置项
const sshBaseItems = [
useFormCustom(() => {
return (
<NGrid cols={24} xGap={4}>
@@ -616,18 +627,43 @@ export const useApiFormController = (props: ApiFormControllerProps): ApiFormCont
{ label: $t('t_48_1745289355714'), value: 'password' },
{ label: $t('t_1_1746667588689'), value: 'key' },
]),
(param.value.config as SshAccessConfig)?.mode === 'password'
? useFormInput($t('t_48_1745289355714'), 'config.password', {
]
// 根据认证模式添加对应的字段
const sshAuthItems = []
if ((param.value.config as SshAccessConfig)?.mode === 'password') {
sshAuthItems.push(
useFormInput($t('t_48_1745289355714'), 'config.password', {
type: 'password',
showPasswordOn: 'click',
allowInput: noSideSpace,
}),
)
} else if ((param.value.config as SshAccessConfig)?.mode === 'key') {
sshAuthItems.push(
useFormTextarea($t('t_1_1746667588689'), 'config.key', {
rows: 3,
placeholder: $t('t_0_1747709067998'),
}),
// 私钥密码输入框(使用 password 字段)
useFormInput(
'私钥密码',
'config.password',
{
type: 'password',
showPasswordOn: 'click',
allowInput: noSideSpace,
})
: useFormTextarea($t('t_1_1746667588689'), 'config.key', {
rows: 3,
placeholder: $t('t_0_1747709067998'),
}),
)
placeholder: '请输入私钥密码(可选)',
},
{ showRequireMark: false },
),
)
}
// 合并所有 SSH 配置项
items.push(...sshBaseItems, ...sshAuthItems)
break
}
case '1panel':
items.push(
// 1Panel版本选择下拉框

View File

@@ -0,0 +1,646 @@
import { defineComponent, onMounted, ref } from 'vue'
import { useRoute, useRouter } from 'vue-router'
import { NButton, NCard, NSpin, NIcon, NSpace, NText, NEmpty, NDataTable, NPagination } from 'naive-ui'
import { ArrowLeft, Information, ErrorOutline } from '@vicons/carbon'
import { useThemeCssVar } from '@baota/naive-ui/theme'
import { useTable } from '@baota/naive-ui/hooks'
// 工具和钩子
import { useError } from '@baota/hooks/error'
// API和类型
import { getMonitorDetail, getMonitorErrorRecord } from '@/api/monitor'
import type { MonitorDetailInfo, ErrorRecord, GetErrorRecordParams, CertChainNode } from '@/types/monitor'
/**
* 错误列表卡片组件
*/
const ErrorListCard = defineComponent({
name: 'ErrorListCard',
props: {
monitorId: {
type: Number,
required: true,
},
},
setup(props) {
const { handleError } = useError()
/**
* 格式化日期时间
*/
const formatDateTime = (dateStr: string): string => {
if (!dateStr) return '-'
return new Date(dateStr).toLocaleString('zh-CN')
}
console.log('ErrorListCard 渲染monitorId:', props.monitorId)
// 错误记录表格配置
const errorColumns = [
{
title: '错误时间',
key: 'create_time',
width: 200,
render: (row: ErrorRecord) => (
<span class="text-[1.4rem] sm:text-[1.5rem] font-mono">{formatDateTime(row.create_time)}</span>
),
},
{
title: '错误消息',
key: 'msg',
render: (row: ErrorRecord) => (
<div class="text-[1.4rem] sm:text-[1.5rem] text-red-600 dark:text-red-400 break-words leading-relaxed">
<div class="max-w-full overflow-hidden">
<div class="whitespace-pre-wrap break-all">{row.msg || '-'}</div>
</div>
</div>
),
},
]
// 错误记录请求函数
const errorRecordRequest = async <T = ErrorRecord,>(params: GetErrorRecordParams) => {
console.log('🔍 错误记录请求开始,参数:', params)
console.log('🔍 API端点: /v1/monitor/get_err_record')
try {
const apiInstance = getMonitorErrorRecord(params)
console.log('🔍 API实例创建成功:', apiInstance)
const response = await apiInstance.fetch()
console.log('✅ 错误记录API响应成功:', response)
const { data, count, status, message } = response
console.log('📊 响应详情:', { data, count, status, message })
const result = {
list: (data || []) as T[],
total: count || 0,
}
console.log('🎯 错误记录处理结果:', result)
return result
} catch (error: unknown) {
console.error('❌ 错误记录请求失败:', error)
if (error instanceof Error) {
console.error('❌ 错误消息:', error.message)
console.error('❌ 错误堆栈:', error.stack)
}
handleError(error).default('获取错误记录失败,请稍后重试')
return { list: [] as T[], total: 0 }
}
}
// 创建表格实例
const {
TableComponent,
PageComponent,
loading: errorLoading,
fetch: fetchErrorList,
} = useTable<ErrorRecord, GetErrorRecordParams>({
config: errorColumns,
request: errorRecordRequest,
defaultValue: ref({
id: props.monitorId,
p: 1,
limit: 10,
}),
alias: { page: 'p', pageSize: 'limit' },
watchValue: ['p', 'limit'], // 监听分页参数变化
})
// 组件挂载时加载错误记录
onMounted(async () => {
console.log('🚀 ErrorListCard 挂载,开始加载错误记录')
console.log('🚀 监控ID:', props.monitorId)
// 使用useTable的fetch方法加载数据
try {
console.log('📊 使用useTable fetch方法...')
await fetchErrorList()
console.log('✅ 错误记录加载完成')
} catch (error) {
console.error('❌ 错误记录加载失败:', error)
}
})
return () => (
<NCard
title="错误列表"
class="h-fit [&_.n-card-header_.n-card-header__main]:text-[1.8rem] [&_.n-card-header_.n-card-header__main]:font-medium"
bordered
>
{{
'header-extra': () => (
<NIcon size="20" color="var(--n-error-color)">
<ErrorOutline />
</NIcon>
),
default: () => (
<div class="space-y-4">
<NSpin show={errorLoading.value}>
<TableComponent>
{{
empty: () => (
<NEmpty
description="暂无错误记录"
size="large"
class="[&_.n-empty__description]:text-[1.6rem] py-8"
>
{{
icon: () => (
<NIcon size="48" color="var(--n-text-color-disabled)">
<ErrorOutline />
</NIcon>
),
}}
</NEmpty>
),
}}
</TableComponent>
</NSpin>
<div class="flex justify-end mt-4">
<PageComponent />
</div>
</div>
),
}}
</NCard>
)
},
})
/**
* @component MonitorDetailView
* @description 监控详情页面组件
* 负责展示监控的详细信息,包括基本信息和证书内容信息
*/
export default defineComponent({
name: 'MonitorDetailView',
setup() {
const route = useRoute()
const router = useRouter()
const { handleError } = useError()
// 响应式数据
const loading = ref(false)
const detailData = ref<MonitorDetailInfo | null>(null)
const monitorId = ref<number>(Number(route.query.id))
// 获取主题CSS变量
const cssVars = useThemeCssVar([
'contentPadding',
'borderColor',
'headerHeight',
'iconColorHover',
'successColor',
'errorColor',
'warningColor',
'primaryColor',
])
/**
* 返回监控列表页面
*/
const goBack = (): void => {
router.push('/monitor')
}
/**
* 获取监控详情数据
*/
const fetchDetailData = async (): Promise<void> => {
if (!monitorId.value) {
handleError(new Error('监控ID无效')).default('无效的监控ID请返回监控列表重试')
return
}
try {
loading.value = true
const { data, status } = await getMonitorDetail({ id: monitorId.value }).fetch()
if (status && data) {
detailData.value = data
} else {
handleError(new Error('获取监控详情失败')).default('获取监控详情失败,请稍后重试')
}
} catch (error) {
handleError(error).default('获取监控详情失败,请稍后重试')
} finally {
loading.value = false
}
}
/**
* 格式化日期时间
*/
const formatDateTime = (dateStr: string): string => {
if (!dateStr) return '-'
return new Date(dateStr).toLocaleString('zh-CN')
}
/**
* 格式化证书有效期范围
*/
const formatValidityPeriod = (notBefore: string, notAfter: string): string => {
if (!notBefore || !notAfter) return '-'
const startDate = formatDateTime(notBefore)
const endDate = formatDateTime(notAfter)
return `${startDate}${endDate}`
}
/**
* 获取验证状态显示文本和颜色
*/
const getValidStatus = (valid: number) => {
return valid === 1
? { text: '有效', color: 'var(--n-success-color)' }
: { text: '无效', color: 'var(--n-error-color)' }
}
/**
* 获取剩余天数的颜色
*/
const getDaysLeftColor = (daysLeft: number): string => {
if (daysLeft <= 7) return 'var(--n-error-color)'
if (daysLeft <= 30) return 'var(--n-warning-color)'
return 'var(--n-success-color)'
}
/**
* 递归渲染证书链节点
*/
const renderCertChainNode = (node: CertChainNode, level: number = 0, index: number = 0): JSX.Element[] => {
const elements: JSX.Element[] = []
// 确定证书类型和样式
const getCertTypeInfo = (level: number, hasChildren: boolean) => {
if (level === 0) {
return {
label: '终端证书',
color: 'bg-green-500',
textColor: 'text-green-700 dark:text-green-400',
}
} else if (hasChildren) {
return {
label: `中间证书 #${index + 1}`,
color: 'bg-blue-500',
textColor: 'text-blue-700 dark:text-blue-400',
}
} else {
return {
label: '根证书',
color: 'bg-purple-500',
textColor: 'text-purple-700 dark:text-purple-400',
}
}
}
const typeInfo = getCertTypeInfo(level, node.children && node.children.length > 0)
// 渲染当前节点
elements.push(
<div
key={`cert-${level}-${index}`}
class="flex items-center space-x-3 p-3 bg-white dark:bg-gray-800 rounded-lg shadow-sm"
style={{ marginLeft: `${level * 1.5}rem` }}
>
<div class={`w-3 h-3 ${typeInfo.color} rounded-full flex-shrink-0 shadow-sm`}></div>
<div class="flex-1">
<span class={`text-[1.4rem] sm:text-[1.5rem] font-medium ${typeInfo.textColor}`}>{typeInfo.label}</span>
<div class="text-[1.3rem] sm:text-[1.4rem] text-gray-600 dark:text-gray-400 font-mono mt-1 break-words">
{node.common_name}
</div>
</div>
</div>,
)
// 递归渲染子节点
if (node.children && node.children.length > 0) {
node.children.forEach((child: CertChainNode, childIndex: number) => {
elements.push(...renderCertChainNode(child, level + 1, childIndex))
})
}
return elements
}
// 组件挂载时获取数据
onMounted(() => {
fetchDetailData()
})
return () => (
<div class="mx-auto max-w-[1800px] w-full p-4 sm:p-6 lg:p-8" style={cssVars.value}>
<NSpin show={loading.value}>
{/* 页面头部 */}
<div class="mb-6 sm:mb-8">
<NSpace align="center" class="mb-4 sm:mb-5">
<NButton
size="medium"
type="default"
onClick={goBack}
class="text-[1.4rem] sm:text-[1.5rem]"
renderIcon={() => (
<NIcon>
<ArrowLeft />
</NIcon>
)}
>
</NButton>
</NSpace>
<h1 class="text-[2.2rem] sm:text-[2.4rem] lg:text-[2.6rem] font-semibold text-gray-800 dark:text-gray-200 break-words leading-tight">
{detailData.value?.name || '监控详情'} -
</h1>
</div>
{/* 内容区域 */}
{detailData.value ? (
<div class="space-y-6 sm:space-y-8 lg:space-y-10">
{/* 合并的监控和证书详情模块 */}
<NCard
title="监控详情与证书信息"
class="[&_.n-card-header_.n-card-header__main]:text-[1.8rem] [&_.n-card-header_.n-card-header__main]:font-medium"
bordered
>
{{
'header-extra': () => (
<NIcon size="24" color="var(--n-primary-color)">
<Information />
</NIcon>
),
default: () => (
<div class="space-y-10">
{/* 核心状态信息 - 最重要 */}
<div>
<h4 class="font-semibold mb-6 text-primary text-[1.9rem] sm:text-[2rem] border-b-2 border-primary/20 pb-3">
</h4>
<div class="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-4 gap-6">
<div class="bg-gradient-to-br from-blue-50 to-blue-100 dark:from-blue-900/30 dark:to-blue-800/30 p-5 rounded-xl border border-blue-200 dark:border-blue-700">
<NText
depth="3"
class="text-[1.5rem] sm:text-[1.6rem] font-medium text-blue-700 dark:text-blue-300"
>
</NText>
<div class="mt-3 font-bold text-[1.7rem] sm:text-[1.8rem]">
{detailData.value && (
<span style={{ color: getValidStatus(detailData.value.valid).color }}>
{getValidStatus(detailData.value.valid).text}
</span>
)}
</div>
</div>
<div class="bg-gradient-to-br from-green-50 to-green-100 dark:from-green-900/30 dark:to-green-800/30 p-5 rounded-xl border border-green-200 dark:border-green-700">
<NText
depth="3"
class="text-[1.5rem] sm:text-[1.6rem] font-medium text-green-700 dark:text-green-300"
>
</NText>
<div class="mt-3 font-bold text-[1.7rem] sm:text-[1.8rem]">
{detailData.value && (
<span style={{ color: getDaysLeftColor(detailData.value.days_left) }}>
{detailData.value.days_left}
</span>
)}
</div>
</div>
<div class="bg-gradient-to-br from-purple-50 to-purple-100 dark:from-purple-900/30 dark:to-purple-800/30 p-5 rounded-xl border border-purple-200 dark:border-purple-700">
<NText
depth="3"
class="text-[1.5rem] sm:text-[1.6rem] font-medium text-purple-700 dark:text-purple-300"
>
</NText>
<div class="mt-3 font-bold text-[1.7rem] sm:text-[1.8rem]">
<span
style={{
color:
(detailData.value?.err_count || 0) > 0
? 'var(--n-error-color)'
: 'var(--n-success-color)',
}}
>
{detailData.value?.err_count || 0}
</span>
</div>
</div>
<div class="bg-gradient-to-br from-orange-50 to-orange-100 dark:from-orange-900/30 dark:to-orange-800/30 p-5 rounded-xl border border-orange-200 dark:border-orange-700">
<NText
depth="3"
class="text-[1.5rem] sm:text-[1.6rem] font-medium text-orange-700 dark:text-orange-300"
>
</NText>
<div class="mt-3 font-bold text-[1.7rem] sm:text-[1.8rem] uppercase">
{detailData.value?.monitor_type || '-'}
</div>
</div>
</div>
</div>
{/* 监控配置信息 */}
<div>
<h4 class="font-semibold mb-6 text-primary text-[1.9rem] sm:text-[2rem] border-b-2 border-primary/20 pb-3">
</h4>
<div class="grid grid-cols-1 lg:grid-cols-2 gap-6">
<div class="space-y-5">
<div class="bg-gray-50 dark:bg-gray-800/50 p-5 rounded-lg">
<NText depth="3" class="text-[1.5rem] sm:text-[1.6rem] font-medium">
</NText>
<div class="mt-3 font-medium text-[1.6rem] sm:text-[1.7rem] break-words">
{detailData.value?.name || '-'}
</div>
</div>
<div class="bg-gray-50 dark:bg-gray-800/50 p-5 rounded-lg">
<NText depth="3" class="text-[1.5rem] sm:text-[1.6rem] font-medium">
</NText>
<div class="mt-3 font-medium text-[1.6rem] sm:text-[1.7rem]">
<a
href={`https://${detailData.value?.target}`}
target="_blank"
rel="noopener noreferrer"
class="text-primary hover:underline break-all"
>
{detailData.value?.target || '-'}
</a>
</div>
</div>
</div>
<div class="space-y-5">
<div class="bg-gray-50 dark:bg-gray-800/50 p-5 rounded-lg">
<NText depth="3" class="text-[1.5rem] sm:text-[1.6rem] font-medium">
</NText>
<div class="mt-3 font-medium text-[1.6rem] sm:text-[1.7rem]">
{detailData.value?.ca || '-'}
</div>
</div>
<div class="bg-gray-50 dark:bg-gray-800/50 p-5 rounded-lg">
<NText depth="3" class="text-[1.5rem] sm:text-[1.6rem] font-medium">
</NText>
<div class="mt-3 font-medium text-[1.6rem] sm:text-[1.7rem] break-words">
{formatDateTime(detailData.value?.last_time || '')}
</div>
</div>
{detailData.value?.tls_version && (
<div class="bg-gray-50 dark:bg-gray-800/50 p-5 rounded-lg">
<NText depth="3" class="text-[1.5rem] sm:text-[1.6rem] font-medium">
TLS版本
</NText>
<div class="mt-3 font-medium text-[1.6rem] sm:text-[1.7rem]">
{detailData.value.tls_version}
</div>
</div>
)}
</div>
</div>
</div>
{/* 证书基本信息 */}
<div>
<h4 class="font-semibold mb-6 text-success text-[1.9rem] sm:text-[2rem] border-b-2 border-success/20 pb-3">
</h4>
<div class="grid grid-cols-1 lg:grid-cols-2 gap-6">
<div class="bg-green-50 dark:bg-green-900/20 p-6 rounded-xl border border-green-200 dark:border-green-800">
<NText
depth="3"
class="text-[1.5rem] sm:text-[1.6rem] font-medium text-green-700 dark:text-green-400"
>
(CN)
</NText>
<div class="mt-3 font-mono text-[1.6rem] sm:text-[1.7rem] text-green-800 dark:text-green-300 break-all leading-relaxed">
{detailData.value?.common_name || '-'}
</div>
</div>
<div class="bg-blue-50 dark:bg-blue-900/20 p-6 rounded-xl border border-blue-200 dark:border-blue-800">
<NText
depth="3"
class="text-[1.5rem] sm:text-[1.6rem] font-medium text-blue-700 dark:text-blue-400"
>
(SAN)
</NText>
<div class="mt-3 font-mono text-[1.6rem] sm:text-[1.7rem] text-blue-800 dark:text-blue-300 break-all leading-relaxed">
{detailData.value?.sans || '-'}
</div>
</div>
</div>
</div>
{/* 有效期详情 */}
<div>
<h4 class="font-semibold mb-6 text-success text-[1.9rem] sm:text-[2rem] border-b-2 border-success/20 pb-3">
</h4>
<div class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-6">
<div class="bg-gradient-to-br from-green-50 to-emerald-50 dark:from-green-900/30 dark:to-emerald-900/30 p-6 rounded-xl border border-green-200 dark:border-green-700">
<NText
depth="3"
class="text-[1.5rem] sm:text-[1.6rem] font-medium text-green-700 dark:text-green-300"
>
</NText>
<div class="mt-3 font-mono text-[1.6rem] sm:text-[1.7rem] text-green-600 dark:text-green-400 break-words">
{formatDateTime(detailData.value?.not_before || '')}
</div>
</div>
<div class="bg-gradient-to-br from-orange-50 to-red-50 dark:from-orange-900/30 dark:to-red-900/30 p-6 rounded-xl border border-orange-200 dark:border-orange-700">
<NText
depth="3"
class="text-[1.5rem] sm:text-[1.6rem] font-medium text-orange-700 dark:text-orange-300"
>
</NText>
<div class="mt-3 font-mono text-[1.6rem] sm:text-[1.7rem] text-orange-600 dark:text-orange-400 break-words">
{formatDateTime(detailData.value?.not_after || '')}
</div>
</div>
<div class="bg-gradient-to-br from-purple-50 to-indigo-50 dark:from-purple-900/30 dark:to-indigo-900/30 p-6 rounded-xl border border-purple-200 dark:border-purple-700 md:col-span-2 lg:col-span-1">
<NText
depth="3"
class="text-[1.5rem] sm:text-[1.6rem] font-medium text-purple-700 dark:text-purple-300"
>
</NText>
<div class="mt-3 font-bold text-[1.7rem] sm:text-[1.8rem]">
{detailData.value && (
<span style={{ color: getDaysLeftColor(detailData.value.days_left) }}>
{detailData.value.days_left}
</span>
)}
</div>
</div>
</div>
<div class="mt-6 bg-gray-50 dark:bg-gray-800/50 p-5 rounded-lg">
<NText depth="3" class="text-[1.5rem] sm:text-[1.6rem] font-medium">
</NText>
<div class="mt-3 font-medium text-[1.6rem] sm:text-[1.7rem] break-words">
{formatValidityPeriod(
detailData.value?.not_before || '',
detailData.value?.not_after || '',
)}
</div>
</div>
</div>
{/* 证书链路信息 - 视觉增强 */}
{detailData.value?.cert_chain && (
<div>
<h4 class="font-semibold mb-6 text-success text-[1.9rem] sm:text-[2rem] border-b-2 border-success/20 pb-3">
</h4>
<div class="bg-gradient-to-r from-blue-50 to-indigo-50 dark:from-blue-900/20 dark:to-indigo-900/20 p-8 rounded-xl border border-blue-200 dark:border-blue-800">
<div class="space-y-5">{renderCertChainNode(detailData.value.cert_chain)}</div>
</div>
</div>
)}
{/* 验证错误信息 */}
{detailData.value?.verify_error && (
<div>
<h4 class="font-semibold mb-6 text-error text-[1.9rem] sm:text-[2rem] border-b-2 border-error/20 pb-3">
</h4>
<div class="bg-red-50 dark:bg-red-900/20 p-6 rounded-xl border border-red-200 dark:border-red-800">
<div class="text-red-600 dark:text-red-300 text-[1.6rem] sm:text-[1.7rem] leading-relaxed break-words">
{detailData.value.verify_error}
</div>
</div>
</div>
)}
</div>
),
}}
</NCard>
{/* 错误列表模块 */}
<ErrorListCard monitorId={monitorId.value} />
</div>
) : (
!loading.value && (
<NCard bordered class="text-center [&_.n-empty__description]:text-[1.6rem]">
<NEmpty description="未找到监控详情数据" size="large">
{{
extra: () => (
<NButton type="primary" class="text-[1.4rem]" onClick={goBack}>
</NButton>
),
}}
</NEmpty>
</NCard>
)
)}
</NSpin>
</div>
)
},
})

View File

@@ -0,0 +1,299 @@
import { defineComponent, ref, computed } from 'vue'
import { NTabs, NTabPane, NUpload, NUploadDragger, NButton, NSpace, NText, NIcon, NCard, NDivider } from 'naive-ui'
import { CloudUploadOutline, DocumentOutline, DownloadOutline } from '@vicons/ionicons5'
import { $t } from '@locales/index'
import { useMessage } from '@baota/naive-ui/hooks'
import { useError } from '@baota/hooks/error'
import { fileImportMonitor, downloadMonitorTemplate } from '@/api/monitor'
import type { UploadFileInfo } from 'naive-ui'
import type { SupportedFileType, FileUploadStatus } from '@/types/monitor'
/**
* 导入监控弹窗组件
* @description 提供文件导入和模板下载功能的弹窗界面
*/
export default defineComponent({
name: 'ImportMonitorModal',
setup(_, { emit }) {
// 消息提示和错误处理
const message = useMessage()
const { handleError } = useError()
// 当前激活的标签页
const activeTab = ref<'import' | 'template'>('import')
// 文件上传状态
const uploadStatus = ref<FileUploadStatus>({
uploading: false,
progress: 0,
success: false,
})
// 支持的文件格式
const supportedFormats: SupportedFileType[] = ['txt', 'csv', 'json', 'xlsx']
// 文件格式验证
const validateFileType = (file: File): boolean => {
const extension = file.name.split('.').pop()?.toLowerCase() as SupportedFileType
return supportedFormats.includes(extension)
}
// 文件大小验证限制为10MB
const validateFileSize = (file: File): boolean => {
const maxSize = 10 * 1024 * 1024 // 10MB
return file.size <= maxSize
}
/**
* 处理文件上传前的验证
*/
const handleBeforeUpload = (data: { file: UploadFileInfo; fileList: UploadFileInfo[] }): boolean => {
const file = data.file.file
if (!file) return false
// 验证文件类型
if (!validateFileType(file)) {
message.error($t('t_9_1753000000001'))
return false
}
// 验证文件大小
if (!validateFileSize(file)) {
message.error($t('t_10_1753000000001'))
return false
}
return true
}
/**
* 处理文件上传
*/
const handleFileUpload = async (options: {
file: UploadFileInfo
onProgress: (e: { percent: number }) => void
}) => {
const file = options.file.file
if (!file) return
try {
uploadStatus.value = {
uploading: true,
progress: 0,
success: false,
}
// 模拟上传进度
const progressInterval = setInterval(() => {
if (uploadStatus.value.progress < 90) {
uploadStatus.value.progress += 10
options.onProgress({ percent: uploadStatus.value.progress })
}
}, 200)
// 创建FormData并上传文件
const formData = new FormData()
formData.append('file', file)
// 使用原生fetch进行文件上传因为useApi可能不支持FormData
const response = await fetch('/v1/monitor/file_add_monitor', {
method: 'POST',
body: formData,
})
if (!response.ok) {
throw new Error(`上传失败: ${response.statusText}`)
}
const result = await response.json()
clearInterval(progressInterval)
uploadStatus.value = {
uploading: false,
progress: 100,
success: true,
}
options.onProgress({ percent: 100 })
// 显示上传结果
if (result.data) {
const { success_count, failed_count } = result.data
message.success(
$t('t_14_1753000000001')
.replace('{success}', success_count.toString())
.replace('{failed}', failed_count.toString()),
)
// 通知父组件刷新数据
emit('success')
} else {
message.success($t('t_15_1753000000001'))
emit('success')
}
} catch (error) {
uploadStatus.value = {
uploading: false,
progress: 0,
success: false,
error: $t('t_13_1753000000001'),
}
handleError(error).default($t('t_16_1753000000001'))
}
}
/**
* 下载模板文件
*/
const handleDownloadTemplate = async (type: SupportedFileType) => {
try {
// 使用原生fetch下载模板文件
const response = await fetch(`/v1/monitor/template?type=${type}`, {
method: 'GET',
})
if (!response.ok) {
throw new Error(`下载模板失败: ${response.statusText}`)
}
const blob = await response.blob()
// 根据文件类型设置正确的文件名
const fileName = `monitor_template.${type}`
// 创建下载链接
const url = window.URL.createObjectURL(blob)
const link = document.createElement('a')
link.href = url
link.download = fileName
link.style.display = 'none'
document.body.appendChild(link)
link.click()
document.body.removeChild(link)
window.URL.revokeObjectURL(url)
message.success(`${type.toUpperCase()} ${$t('t_17_1753000000001')}`)
} catch (error) {
handleError(error).default($t('t_18_1753000000001'))
}
}
// 计算上传提示文本
const uploadTipText = computed(() => {
if (uploadStatus.value.uploading) {
return `${$t('t_11_1753000000001')} ${uploadStatus.value.progress}%`
}
if (uploadStatus.value.success) {
return $t('t_12_1753000000001')
}
if (uploadStatus.value.error) {
return uploadStatus.value.error
}
return $t('t_4_1753000000001')
})
return () => (
<div class="import-monitor-modal">
<NTabs value={activeTab.value} onUpdateValue={(value) => (activeTab.value = value as 'import' | 'template')}>
{/* 文件导入标签页 */}
<NTabPane name="import" tab={$t('t_1_1753000000001')}>
<div class="p-6">
<NCard title={$t('t_3_1753000000001')} class="mb-4">
<NUpload
multiple={false}
accept=".txt,.csv,.json,.xlsx"
showFileList={false}
onBeforeUpload={handleBeforeUpload}
customRequest={handleFileUpload}
>
<NUploadDragger class="min-h-[200px]">
<div class="text-center">
<NIcon size={48} class="text-primary mb-4">
<CloudUploadOutline />
</NIcon>
<NText class="text-lg block mb-2">{uploadTipText.value}</NText>
<NText depth="3" class="text-sm">
{$t('t_5_1753000000001')}
</NText>
</div>
</NUploadDragger>
</NUpload>
</NCard>
<NDivider />
<NCard title={$t('t_6_1753000000001')} class="mt-4">
<div class="space-y-3">
<div>
<NText strong>CSV格式</NText>
<NText depth="3" class="ml-2">
,,,
</NText>
</div>
<div>
<NText strong>JSON格式</NText>
<NText depth="3" class="ml-2">{`[{"name":"","domain":"","protocol":"","port":""}]`}</NText>
</div>
<div>
<NText strong>Excel格式</NText>
<NText depth="3" class="ml-2">
</NText>
</div>
</div>
</NCard>
</div>
</NTabPane>
{/* 模板下载标签页 */}
<NTabPane name="template" tab={$t('t_2_1753000000001')}>
<div class="p-6">
<NCard title={$t('t_7_1753000000001')}>
<NText class="block mb-6" depth="3">
{$t('t_8_1753000000001')}
</NText>
<NSpace vertical size="large">
{supportedFormats.map((format) => (
<div key={format} class="flex items-center justify-between p-4 border border-gray-200 rounded-lg">
<div class="flex items-center">
<NIcon size={24} class="mr-3 text-primary">
<DocumentOutline />
</NIcon>
<div>
<NText strong class="block">
{format.toUpperCase()}
</NText>
<NText depth="3" class="text-sm">
{format === 'xlsx' ? 'Excel' : format.toUpperCase()}
</NText>
</div>
</div>
<NButton
type="primary"
size="small"
onClick={() => handleDownloadTemplate(format)}
v-slots={{
icon: () => (
<NIcon>
<DownloadOutline />
</NIcon>
),
}}
>
</NButton>
</div>
))}
</NSpace>
</NCard>
</div>
</NTabPane>
</NTabs>
</div>
)
},
})

View File

@@ -1,9 +1,10 @@
import { defineComponent, onMounted } from 'vue'
import { NButton, NInput } from 'naive-ui'
import { NButton, NSpace } from 'naive-ui'
import { Search } from '@vicons/carbon'
import { $t } from '@locales/index'
import { useThemeCssVar } from '@baota/naive-ui/theme'
import { RouterView } from '@baota/router'
import { useController } from './useController'
@@ -18,8 +19,17 @@ export default defineComponent({
name: 'MonitorManage',
setup() {
// 使用控制器获取数据和方法
const { TableComponent, PageComponent, SearchComponent, fetch, openAddForm, isDetectionAddMonitor } =
useController()
const {
TableComponent,
PageComponent,
ColumnSettingsComponent,
SearchComponent,
fetch,
openAddForm,
openImportForm,
isDetectionAddMonitor,
hasChildRoutes,
} = useController()
// 获取主题CSS变量
const cssVar = useThemeCssVar(['contentPadding', 'borderColor', 'headerHeight', 'iconColorHover'])
@@ -36,36 +46,50 @@ export default defineComponent({
return () => (
<div class="h-full flex flex-col" style={cssVar.value}>
<div class="mx-auto max-w-[1600px] w-full p-6">
<BaseComponent
v-slots={{
// 头部左侧区域 - 添加按钮
headerLeft: () => (
<NButton type="primary" size="large" class="px-5" onClick={openAddForm}>
{$t('t_11_1745289354516')}
</NButton>
),
// 头部右侧区域 - 搜索框
headerRight: () => <SearchComponent placeholder={$t('t_12_1745289356974')} />,
// 内容区域 - 监控表格
content: () => (
<div class="rounded-lg">
<TableComponent
size="medium"
scroll-x="1800"
v-slots={{
empty: () => <EmptyState addButtonText={$t('t_11_1745289354516')} onAddClick={openAddForm} />,
}}
/>
</div>
),
// 底部右侧区域 - 分页组件
footerRight: () => (
<div class="mt-4 flex justify-end">
<PageComponent />
</div>
),
}}
></BaseComponent>
{hasChildRoutes.value ? (
<RouterView />
) : (
<BaseComponent
v-slots={{
// 头部左侧区域 - 添加按钮和导入按钮
headerLeft: () => (
<NSpace>
<NButton type="primary" size="large" class="px-5" onClick={openAddForm}>
{$t('t_11_1745289354516')}
</NButton>
<NButton type="default" size="large" class="px-5" onClick={openImportForm}>
{$t('t_0_1753000000001')}
</NButton>
</NSpace>
),
// 头部右侧区域 - 搜索框和列设置
headerRight: () => (
<NSpace align="center" size="medium">
<SearchComponent placeholder={$t('t_12_1745289356974')} />
<ColumnSettingsComponent />
</NSpace>
),
// 内容区域 - 监控表格
content: () => (
<div class="rounded-lg">
<TableComponent
size="medium"
scroll-x="1800"
v-slots={{
empty: () => <EmptyState addButtonText={$t('t_11_1745289354516')} onAddClick={openAddForm} />,
}}
/>
</div>
),
// 底部右侧区域 - 分页组件
footerRight: () => (
<div class="mt-4 flex justify-end">
<PageComponent />
</div>
),
}}
></BaseComponent>
)}
</div>
</div>
)

View File

@@ -1,6 +1,6 @@
import { computed, onMounted, onUnmounted } from 'vue'
import { useRoute, useRouter } from 'vue-router'
import { FormRules, NButton, NSpace, NSwitch, type DataTableColumns } from 'naive-ui'
import { FormRules, NButton, NSpace, NSwitch, NText, NDivider, type DataTableColumns } from 'naive-ui'
// 钩子和工具
import {
@@ -20,11 +20,12 @@ import { $t } from '@locales/index'
// Store和组件
import { useStore } from './useStore'
import MonitorForm from './components/AddMonitorModel'
import NotifyProviderSelect from '@components/NotifyProviderSelect'
import ImportMonitorModal from './components/ImportMonitorModal'
import NotifyProviderMultiSelect from '@components/notifyProviderMultiSelect'
import TypeIcon from '@components/TypeIcon'
// 类型导入
import type { Ref } from 'vue'
import type { Ref, ComputedRef } from 'vue'
import type {
AddSiteMonitorParams,
SiteMonitorItem,
@@ -39,6 +40,7 @@ interface MonitorControllerExposes {
// 表格相关
TableComponent: ReturnType<typeof useTable>['TableComponent']
PageComponent: ReturnType<typeof useTable>['PageComponent']
ColumnSettingsComponent: ReturnType<typeof useTable>['ColumnSettingsComponent']
SearchComponent: ReturnType<typeof useSearch>['SearchComponent']
loading: Ref<boolean>
// param: Ref<SiteMonitorListParams>
@@ -47,7 +49,12 @@ interface MonitorControllerExposes {
// 表单和操作相关
openAddForm: () => void
openImportForm: () => void
openDetailPage: (row: SiteMonitorItem) => void
isDetectionAddMonitor: () => void
// 路由相关
hasChildRoutes: ComputedRef<boolean>
}
// 从Store中获取方法
@@ -99,6 +106,9 @@ export const useController = (): MonitorControllerExposes => {
const route = useRoute()
const router = useRouter()
// 判断是否为子路由
const hasChildRoutes = computed(() => route.path !== '/monitor')
/**
* 创建表格列配置
* @description 定义监控表格的列结构和渲染方式
@@ -112,22 +122,27 @@ export const useController = (): MonitorControllerExposes => {
},
{
title: $t('t_17_1745227838561'),
key: 'site_domain',
key: 'target',
width: 180,
render: (row: SiteMonitorItem) => {
return (
<NButton tag="a" text type="primary" href={`https://${row.site_domain}`} target="_blank">
{row.site_domain}
</NButton>
<a
href={`https://${row.target}`}
target="_blank"
rel="noopener noreferrer"
style="color: var(--primary-color); text-decoration: none;"
>
{row.target}
</a>
)
},
},
{
title: $t('t_14_1745289354902'),
key: 'cert_domain',
key: 'common_name',
width: 180,
render: (row: SiteMonitorItem) => {
return row.cert_domain || '-'
return row.common_name || '-'
},
},
{
@@ -137,14 +152,29 @@ export const useController = (): MonitorControllerExposes => {
},
{
title: $t('t_16_1745289354902'),
key: 'state',
key: 'valid',
width: 100,
render: (row: SiteMonitorItem) => {
return row.valid === 1 ? '有效' : '无效'
},
},
{
title: $t('t_17_1745289355715'),
key: 'end_time',
key: 'not_after',
width: 150,
render: (row: SiteMonitorItem) => row.end_time + '(' + row.end_day + ')',
render: (row: SiteMonitorItem) => {
// 检查到期时间和剩余天数是否有效
const hasValidNotAfter = row.not_after && row.not_after !== 'undefined' && row.not_after.trim() !== ''
const hasValidDaysLeft = row.days_left !== undefined && row.days_left !== null && !isNaN(row.days_left)
// 如果任一数据无效,显示占位符
if (!hasValidNotAfter || !hasValidDaysLeft) {
return '-'
}
// 正常情况下显示完整的到期时间信息
return `${row.not_after}(${row.days_left}天)`
},
},
{
title: $t('t_2_1750399515511'),
@@ -166,10 +196,29 @@ export const useController = (): MonitorControllerExposes => {
},
{
title: $t('t_18_1745289354598'),
key: 'report_type',
width: 150,
key: 'report_types',
width: 200, // 增加宽度以适应多选标签
render: (row: SiteMonitorItem) => {
return <TypeIcon icon={row.report_type} />
// 确保 report_types 数据格式正确处理
let reportTypes: string | string[]
if (typeof row.report_types === 'string') {
// 如果是逗号分隔的字符串,转换为数组以支持多选显示
reportTypes = row.report_types ? row.report_types.split(',').filter(Boolean) : []
} else if (Array.isArray(row.report_types)) {
// 如果已经是数组,直接使用
reportTypes = row.report_types
} else {
// 其他情况,设为空数组
reportTypes = []
}
// 如果没有通知类型,显示占位符
if (!reportTypes || (Array.isArray(reportTypes) && reportTypes.length === 0)) {
return <span style="color: var(--n-text-color-disabled); font-size: 12px;">-</span>
}
return <TypeIcon icon={reportTypes} />
},
},
{
@@ -188,12 +237,15 @@ export const useController = (): MonitorControllerExposes => {
{
title: $t('t_8_1745215914610'),
key: 'actions',
width: 150,
width: 200,
fixed: 'right' as const,
align: 'right',
render: (row: SiteMonitorItem) => {
return (
<NSpace justify="end">
<NButton size="tiny" strong secondary type="info" onClick={() => openDetailPage(row)}>
</NButton>
<NButton size="tiny" strong secondary type="primary" onClick={() => openEditForm(row)}>
{$t('t_11_1745215915429')}
</NButton>
@@ -210,13 +262,16 @@ export const useController = (): MonitorControllerExposes => {
* 表格实例
* @description 创建表格实例并管理相关状态
*/
const { TableComponent, PageComponent, loading, param, fetch } = useTable<SiteMonitorItem, SiteMonitorListParams>({
const { TableComponent, PageComponent, ColumnSettingsComponent, loading, param, fetch } = useTable<
SiteMonitorItem,
SiteMonitorListParams
>({
config: createColumns(),
request: fetchMonitorList,
defaultValue: { p: 1, limit: 10, search: '' },
alias: { page: 'p', pageSize: 'limit' },
watchValue: ['p', 'limit'],
storage: 'monitorPageSize',
storage: 'monitorColumnSettings',
})
// 搜索实例
@@ -243,6 +298,22 @@ export const useController = (): MonitorControllerExposes => {
})
}
/**
* 打开导入监控弹窗
* @description 显示导入监控的弹窗
*/
const openImportForm = (): void => {
useModal({
title: $t('t_0_1753000000001'),
area: 600,
component: ImportMonitorModal,
footer: false,
onUpdateShow(show) {
if (!show) fetch()
},
})
}
/**
* 打开编辑监控弹窗
* @description 显示编辑监控的表单弹窗
@@ -261,6 +332,18 @@ export const useController = (): MonitorControllerExposes => {
})
}
/**
* 打开监控详情页面
* @description 跳转到监控详情页面
* @param {SiteMonitorItem} row - 监控项数据
*/
const openDetailPage = (row: SiteMonitorItem): void => {
router.push({
path: '/monitor/detail',
query: { id: row.id.toString() },
})
}
/**
* 确认删除监控
* @description 显示删除确认对话框
@@ -302,13 +385,20 @@ export const useController = (): MonitorControllerExposes => {
}
return {
loading,
fetch,
// 表格相关
TableComponent,
PageComponent,
ColumnSettingsComponent,
SearchComponent,
isDetectionAddMonitor,
loading,
fetch,
// 表单和操作相关
openAddForm,
openImportForm,
openDetailPage,
isDetectionAddMonitor,
// 路由相关
hasChildRoutes,
}
}
@@ -327,7 +417,7 @@ interface MonitorFormControllerExposes {
*/
export const useMonitorFormController = (data: UpdateSiteMonitorParams | null = null): MonitorFormControllerExposes => {
// 表单工具
const { useFormInput, useFormCustom, useFormInputNumber } = useFormHooks()
const { useFormInput, useFormCustom, useFormInputNumber, useFormSelect, useFormSwitch } = useFormHooks()
// 加载遮罩
const { open: openLoad, close: closeLoad } = useLoadingMask({ text: '正在提交信息,请稍后...' })
@@ -335,27 +425,71 @@ export const useMonitorFormController = (data: UpdateSiteMonitorParams | null =
// 消息和对话框
const { confirm } = useModalHooks()
/**
* 创建分组标题
* @param title 分组标题文本
* @returns 分组标题配置
*/
const createGroupTitle = (title: string) => {
return useFormCustom(() => <NDivider style="margin: 12px 0 8px 0; font-weight: 500;">{title}</NDivider>)
}
/**
* 表单配置
* @description 定义表单字段和布局
*/
const config = computed(() => [
useFormInput('名称', 'name'),
useFormInput('域名/IP地址', 'domain'),
useFormInput('域名/IP地址', 'target'),
useFormSelect('协议类型', 'monitor_type', [
{ label: 'HTTPS', value: 'https' },
{ label: 'SMTP', value: 'smtp' },
]),
useFormInputNumber('周期(分钟)', 'cycle', { class: 'w-full' }),
useFormCustom(() => {
// 确保 report_types 是数组格式
const currentValue = Array.isArray(monitorForm.value.report_types)
? monitorForm.value.report_types
: monitorForm.value.report_types
? typeof monitorForm.value.report_types === 'string'
? monitorForm.value.report_types.split(',').filter(Boolean)
: [monitorForm.value.report_types]
: []
return (
<NotifyProviderSelect
path="report_type"
<NotifyProviderMultiSelect
path="report_types"
isAddMode={true}
value={monitorForm.value.report_type}
value={currentValue}
valueType="type"
onUpdate:value={(item) => {
monitorForm.value.report_type = item.value
onUpdate:value={(items) => {
// 将选中的多个值转换为数组格式,存储类型值
monitorForm.value.report_types = items.map((item) => item.type || item.value)
}}
/>
)
}),
// 到期提醒设置分组
createGroupTitle('到期提醒设置'),
useFormInputNumber('提前天数', 'advance_day', { class: 'w-full', min: 1, max: 365 }),
useFormCustom(() => {
const advanceDay = monitorForm.value.advance_day || 90
return (
<NText
depth="3"
style="font-size: 12px; margin-top: -8px; margin-bottom: 8px; display: block; color: var(--n-text-color-disabled);"
>
{advanceDay}
</NText>
)
}),
// 连续失败通知设置分组
createGroupTitle('连续失败通知设置'),
useFormInputNumber('重复发送间隔(次数)', 'repeat_send_gap', { class: 'w-full', min: 1, max: 100 }),
useFormSwitch('启用状态', 'active', {
checkedValue: 1,
uncheckedValue: 0,
}),
])
/**
@@ -363,11 +497,11 @@ export const useMonitorFormController = (data: UpdateSiteMonitorParams | null =
*/
const rules = {
name: { required: true, message: '请输入名称', trigger: 'input' },
domain: {
target: {
required: true,
message: '请输入正确的域名或IP地址',
trigger: 'input',
validator: (rule: any, value: any, callback: any) => {
validator: (_rule: any, value: any, callback: any) => {
if (!isDomainWithPort(value)) {
callback(new Error('请输入正确的域名或IP地址支持域名:端口或IP:端口格式)'))
} else {
@@ -375,8 +509,30 @@ export const useMonitorFormController = (data: UpdateSiteMonitorParams | null =
}
},
},
monitor_type: { required: true, message: '请选择协议类型', trigger: 'change' },
cycle: { required: true, message: '请输入周期', trigger: 'input', type: 'number', min: 1, max: 365 },
report_type: { required: true, message: '请选择消息通知类型', trigger: 'change' },
report_types: {
required: true,
message: '请选择消息通知类型',
trigger: 'change',
validator: (_rule: any, value: any, callback: any) => {
if (!value || (Array.isArray(value) && value.length === 0)) {
callback(new Error('请至少选择一种消息通知类型'))
} else {
callback()
}
},
},
advance_day: { required: true, message: '请输入提前天数', trigger: 'input', type: 'number', min: 1, max: 365 },
repeat_send_gap: {
required: true,
message: '请输入重复发送间隔',
trigger: 'input',
type: 'number',
min: 1,
max: 100,
},
active: { required: true, message: '请选择启用状态', trigger: 'change', type: 'number' },
} as FormRules
/**
@@ -387,10 +543,9 @@ export const useMonitorFormController = (data: UpdateSiteMonitorParams | null =
const request = async (params: AddSiteMonitorParams | UpdateSiteMonitorParams): Promise<void> => {
try {
if (data) {
await updateExistingMonitor({ ...params, id: data.id })
await updateExistingMonitor({ ...params, id: data.id } as UpdateSiteMonitorParams)
} else {
const { id, ...rest } = params
await addNewMonitor(rest)
await addNewMonitor(params as AddSiteMonitorParams)
}
} catch (error) {
handleError(error).default('添加失败')

View File

@@ -51,9 +51,13 @@ export const useMonitorStore = defineStore('monitor-store', (): MonitorStoreExpo
const monitorForm = ref<AddSiteMonitorParams & UpdateSiteMonitorParams>({
id: 0,
name: '',
domain: '',
target: '',
monitor_type: 'https', // 默认协议类型为HTTPS
report_types: [], // 默认为空数组,支持多选
cycle: 1,
report_type: '',
repeat_send_gap: 10, // 默认重复发送间隔10次
active: 1, // 默认启用状态
advance_day: 90, // 默认提前90天
})
// -------------------- 方法定义 --------------------
@@ -84,7 +88,13 @@ export const useMonitorStore = defineStore('monitor-store', (): MonitorStoreExpo
*/
const addNewMonitor = async (params: AddSiteMonitorParams): Promise<boolean> => {
try {
const { fetch, message } = addSiteMonitor(params)
// 转换 report_types 数组为逗号分隔的字符串
const processedParams = {
...params,
report_types: Array.isArray(params.report_types) ? params.report_types.join(',') : params.report_types || '',
}
const { fetch, message } = addSiteMonitor(processedParams)
message.value = true
await fetch()
return true
@@ -102,7 +112,13 @@ export const useMonitorStore = defineStore('monitor-store', (): MonitorStoreExpo
*/
const updateExistingMonitor = async (params: UpdateSiteMonitorParams): Promise<boolean> => {
try {
const { fetch, message } = updateSiteMonitor(params)
// 转换 report_types 数组为逗号分隔的字符串
const processedParams = {
...params,
report_types: Array.isArray(params.report_types) ? params.report_types.join(',') : params.report_types || '',
}
const { fetch, message } = updateSiteMonitor(processedParams)
message.value = true
await fetch()
return true
@@ -150,12 +166,37 @@ export const useMonitorStore = defineStore('monitor-store', (): MonitorStoreExpo
/**
* 更新监控表单
* @description 用于编辑时填充表单数据
* @description 用于编辑时填充表单数据,支持单选到多选的数据转换
* @param {UpdateSiteMonitorParams | null} params - 更新监控参数
*/
const updateMonitorForm = (params: UpdateSiteMonitorParams | null = monitorForm.value): void => {
const { id, name, domain, cycle, report_type } = params || monitorForm.value
monitorForm.value = { id, name, domain, cycle, report_type }
const { id, name, target, monitor_type, report_types, cycle, repeat_send_gap, active, advance_day } =
params || monitorForm.value
// 处理 report_types 的数据格式转换
let processedReportTypes: string[]
if (typeof report_types === 'string') {
// 如果是逗号分隔的字符串,转换为数组
processedReportTypes = report_types ? report_types.split(',').filter(Boolean) : []
} else if (Array.isArray(report_types)) {
// 如果已经是数组,直接使用
processedReportTypes = report_types
} else {
// 其他情况,设为空数组
processedReportTypes = []
}
monitorForm.value = {
id,
name,
target,
monitor_type,
report_types: processedReportTypes,
cycle,
repeat_send_gap,
active,
advance_day,
}
}
/**
@@ -166,9 +207,13 @@ export const useMonitorStore = defineStore('monitor-store', (): MonitorStoreExpo
monitorForm.value = {
id: 0,
name: '',
domain: '',
target: '',
monitor_type: 'https', // 默认协议类型为HTTPS
report_types: [], // 重置为空数组
cycle: 1,
report_type: '',
repeat_send_gap: 10, // 默认重复发送间隔10次
active: 1, // 默认启用状态
advance_day: 90, // 默认提前90天
}
}

View File

@@ -8,30 +8,32 @@ export {}
/* prettier-ignore */
declare module 'vue' {
export interface GlobalComponents {
AddNode: typeof import('./../src/components/FlowChart/components/other/addNode/index.tsx')['default']
Alias: typeof import('./../src/components/FlowChart/lib/alias.tsx')['default']
AddNode: typeof import('./../src/components/flowChart/components/other/addNode/index.tsx')['default']
Alias: typeof import('./../src/components/flowChart/lib/alias.tsx')['default']
BaseLayout: typeof import('./../src/components/BaseLayout/index.tsx')['default']
BaseNode: typeof import('./../src/components/FlowChart/components/base/baseNode/index.tsx')['default']
BranchNode: typeof import('./../src/components/FlowChart/components/base/branchNode/index.tsx')['default']
BaseNode: typeof import('./../src/components/flowChart/components/base/baseNode/index.tsx')['default']
BranchNode: typeof import('./../src/components/flowChart/components/base/branchNode/index.tsx')['default']
CAProviderSelect: typeof import('./../src/components/CAProviderSelect/index.tsx')['default']
ConditionNode: typeof import('./../src/components/FlowChart/components/base/conditionNode/index.tsx')['default']
Config: typeof import('./../src/components/FlowChart/lib/config.tsx')['default']
DnsProviderSelect: typeof import('./../src/components/DnsProviderSelect/index.tsx')['default']
Drawer: typeof import('./../src/components/FlowChart/components/other/drawer.tsx')['default']
EndNode: typeof import('./../src/components/FlowChart/components/base/endNode.tsx')['default']
ErrorNode: typeof import('./../src/components/FlowChart/components/base/errorNode/index.tsx')['default']
FlowChart: typeof import('./../src/components/FlowChart/index.tsx')['default']
ConditionNode: typeof import('./../src/components/flowChart/components/base/conditionNode/index.tsx')['default']
Config: typeof import('./../src/components/flowChart/lib/config.tsx')['default']
Demo: typeof import('./../src/components/notifyProviderMultiSelect/demo.tsx')['default']
DnsProviderSelect: typeof import('./../src/components/dnsProviderSelect/index.tsx')['default']
Drawer: typeof import('./../src/components/flowChart/components/other/drawer.tsx')['default']
EndNode: typeof import('./../src/components/flowChart/components/base/endNode.tsx')['default']
ErrorNode: typeof import('./../src/components/flowChart/components/base/errorNode/index.tsx')['default']
FlowChart: typeof import('./../src/components/flowChart/index.tsx')['default']
LogDisplay: typeof import('./../src/components/LogDisplay/index.tsx')['default']
NodeWrap: typeof import('./../src/components/FlowChart/components/render/nodeWrap.tsx')['default']
NotifyProviderSelect: typeof import('./../src/components/NotifyProviderSelect/index.tsx')['default']
NodeWrap: typeof import('./../src/components/flowChart/components/render/nodeWrap.tsx')['default']
NotifyProviderMultiSelect: typeof import('./../src/components/notifyProviderMultiSelect/index.tsx')['default']
NotifyProviderSelect: typeof import('./../src/components/notifyProviderSelect/index.tsx')['default']
RouterLink: typeof import('vue-router')['RouterLink']
RouterView: typeof import('vue-router')['RouterView']
SvgIcon: typeof import('./../src/components/SvgIcon/index.tsx')['default']
SvgIcon: typeof import('./../src/components/svgIcon/index.tsx')['default']
TableEmptyState: typeof import('./../src/components/TableEmptyState/index.tsx')['default']
TypeIcon: typeof import('./../src/components/TypeIcon/index.tsx')['default']
TypeIcon: typeof import('./../src/components/typeIcon/index.tsx')['default']
UpdateLogModal: typeof import('./../src/components/UpdateLogModal/index.tsx')['default']
UseController: typeof import('./../src/components/CAProviderSelect/useController.tsx')['default']
UseStore: typeof import('./../src/components/FlowChart/useStore.tsx')['default']
Verify: typeof import('./../src/components/FlowChart/lib/verify.tsx')['default']
UseStore: typeof import('./../src/components/flowChart/useStore.tsx')['default']
Verify: typeof import('./../src/components/flowChart/lib/verify.tsx')['default']
}
}

View File

@@ -105,6 +105,7 @@ export default defineConfig({
// targetDir: 'allinssl-gitlab',
// discardChanges: true,
// },
{
repo: 'https://github.com/allinssl/allinssl.git',
branch: '1.0.7',

View File

@@ -2,16 +2,20 @@ import { ref, shallowRef, ShallowRef, Ref, effectScope, watch, onUnmounted, isRe
import {
type DataTableProps,
type DataTableSlots,
type DataTableColumns,
type PaginationProps,
type PaginationSlots,
NDataTable,
NPagination,
NButton,
NDropdown,
NCheckbox,
NIcon,
} from 'naive-ui'
import { translation, TranslationModule, type TranslationLocale } from '../locals/translation'
import { useMessage } from './useMessage'
import type { UseTableOptions, TableInstanceWithComponent, TableResponse } from '../types/table'
import type { UseTableOptions, TableInstanceWithComponent, TableResponse, ColumnVisibility } from '../types/table'
// 获取当前语言
const currentLocale = localStorage.getItem('locale-active') || 'zhCN'
@@ -66,6 +70,67 @@ const savePageSizeToStorage = (storage: string, size: number): void => {
console.warn('保存pageSize到本地存储失败:', error)
}
}
/**
* 从本地存储获取列可见性配置的纯函数
* @param storage 存储的key
* @param columns 表格列配置
* @returns 列可见性配置
*/
const getStoredColumnVisibility = (storage: string, columns: any[]): ColumnVisibility => {
try {
if (!storage) return getDefaultColumnVisibility(columns)
const stored = localStorage.getItem(`table-column-settings-${storage}`)
if (stored) {
const parsedVisibility = JSON.parse(stored) as ColumnVisibility
// 验证存储的配置是否与当前列配置匹配
const defaultVisibility = getDefaultColumnVisibility(columns)
const mergedVisibility: ColumnVisibility = {}
// 合并默认配置和存储配置,确保新增的列默认显示
Object.keys(defaultVisibility).forEach((key) => {
mergedVisibility[key] = Object.prototype.hasOwnProperty.call(parsedVisibility, key)
? parsedVisibility[key]
: defaultVisibility[key]
})
return mergedVisibility
}
} catch (error) {
console.warn('读取本地存储列设置失败:', error)
}
return getDefaultColumnVisibility(columns)
}
/**
* 保存列可见性配置到本地存储的纯函数
* @param storage 存储的key
* @param visibility 列可见性配置
*/
const saveColumnVisibilityToStorage = (storage: string, visibility: ColumnVisibility): void => {
try {
if (storage) localStorage.setItem(`table-column-settings-${storage}`, JSON.stringify(visibility))
} catch (error) {
console.warn('保存列设置到本地存储失败:', error)
}
}
/**
* 获取默认列可见性配置的纯函数
* @param columns 表格列配置
* @returns 默认列可见性配置
*/
const getDefaultColumnVisibility = (columns: any[]): ColumnVisibility => {
const visibility: ColumnVisibility = {}
columns.forEach((column) => {
// 使用类型断言来访问 key 属性
const col = column as any
if (col.key) {
visibility[col.key] = true // 默认所有列都显示
}
})
return visibility
}
/**
* 表格钩子函数
* @param options 表格配置选项
@@ -92,6 +157,70 @@ export default function useTable<T = Record<string, any>, Z extends Record<strin
const props = shallowRef({}) as ShallowRef<DataTableProps> // 表格属性
const { error: errorMsg } = useMessage()
// 列设置状态
const columnVisibility = ref<ColumnVisibility>(getStoredColumnVisibility(storage, config))
// 计算过滤后的列配置
const filteredColumns = computed(() => {
return config.filter((column) => {
const col = column as any
if (!col.key) return true // 没有key的列始终显示
return columnVisibility.value[col.key] !== false
})
})
// 计算可见列的详细宽度信息
const visibleColumnsWidth = computed(() => {
let normalColumnsWidth = 0
let fixedColumnsWidth = 0
let totalWidth = 0
filteredColumns.value.forEach((column) => {
const col = column as any
if (col.width) {
// 处理数字和字符串类型的宽度
const width = typeof col.width === 'string' ? parseInt(col.width) : col.width
if (!isNaN(width)) {
totalWidth += width
if (col.fixed) {
fixedColumnsWidth += width
} else {
normalColumnsWidth += width
}
}
}
})
return {
totalWidth,
normalColumnsWidth,
fixedColumnsWidth,
}
})
// 精确计算动态 scroll-x 值
const dynamicScrollX = computed(() => {
const { totalWidth, normalColumnsWidth, fixedColumnsWidth } = visibleColumnsWidth.value
if (totalWidth <= 0) {
return undefined
}
// 精确的表格补偿计算
// 基于 Naive UI DataTable 的实际渲染需求
const TABLE_BORDER = 2 // 表格边框 (左右各1px)
const TABLE_PADDING = 16 // 表格内边距 (Naive UI 默认)
const SCROLL_COMPENSATION = 4 // 滚动区域补偿
// 总补偿宽度:保守且精确
const totalCompensation = TABLE_BORDER + TABLE_PADDING + SCROLL_COMPENSATION
// 最终宽度 = 实际列宽度 + 精确补偿
const preciseWidth = totalWidth + totalCompensation
return preciseWidth
})
// 分页相关状态
const { page, pageSize } = alias
const pageSizeOptionsRef = ref([10, 20, 50, 100, 200]) // 分页选项
@@ -107,7 +236,6 @@ export default function useTable<T = Record<string, any>, Z extends Record<strin
if ((param.value as Record<string, unknown>)[pageSize]) {
;(param.value as Record<string, unknown>)[pageSize] = getStoredPageSize(storage, 10, pageSizeOptionsRef.value) // 每页条数
console.log('初始化每页条数', (param.value as Record<string, unknown>)[pageSize])
}
/**
@@ -135,6 +263,29 @@ export default function useTable<T = Record<string, any>, Z extends Record<strin
fetchData()
}
/**
* 切换列可见性
* @param columnKey 列的key
*/
const toggleColumnVisibility = (columnKey: string) => {
columnVisibility.value = {
...columnVisibility.value,
[columnKey]: !columnVisibility.value[columnKey],
}
// 保存到本地存储
saveColumnVisibilityToStorage(storage, columnVisibility.value)
}
/**
* 重置列设置
*/
const resetColumnSettings = () => {
const defaultVisibility = getDefaultColumnVisibility(config)
columnVisibility.value = defaultVisibility
// 保存到本地存储
saveColumnVisibilityToStorage(storage, defaultVisibility)
}
/**
* 获取表格数据
*/
@@ -172,19 +323,34 @@ export default function useTable<T = Record<string, any>, Z extends Record<strin
const component = (props: DataTableProps, context: { slots?: DataTableSlots }) => {
const { slots, ...attrs } = props as any
const s2 = context
// 合并动态 scroll-x 值
const mergedProps = {
...props,
...attrs,
}
// 精确的 scroll-x 处理:确保容器宽度与内容宽度完全匹配
if (dynamicScrollX.value) {
// 始终使用动态计算的精确宽度,确保无浏览器自动拉伸
mergedProps.scrollX = dynamicScrollX.value
}
return (
<NDataTable
remote
ref={example}
loading={loading.value}
data={data.value.list}
columns={columns.value}
{...props}
{...attrs}
columns={filteredColumns.value}
scrollbar-props={{
xPlacement: 'top',
}}
{...mergedProps}
>
{{
empty: () => (slots?.empty || s2?.slots?.empty ? slots?.empty() || s2?.slots?.empty() : null),
loading: () => (slots?.loading || s2?.slots?.loading ? slots?.loading() || s2?.slots?.loading() : null),
empty: () => (slots?.empty || s2?.slots?.empty ? slots?.empty?.() || s2?.slots?.empty?.() : null),
loading: () => (slots?.loading || s2?.slots?.loading ? slots?.loading?.() || s2?.slots?.loading?.() : null),
}}
</NDataTable>
)
@@ -215,6 +381,82 @@ export default function useTable<T = Record<string, any>, Z extends Record<strin
)
}
/**
* 渲染列设置组件
*/
const columnSettingsComponent = () => {
// 生成下拉选项
const dropdownOptions = [
{
key: 'header',
type: 'render',
render: () => (
<div style="padding: 8px 12px; font-weight: 500; color: var(--n-text-color);">
{hookT('columnSettings')}
</div>
),
},
{
key: 'divider1',
type: 'divider',
},
...config
.filter((column) => (column as any).key)
.map((column) => {
const col = column as any
return {
key: col.key,
type: 'render',
render: () => (
<div
style="padding: 4px 12px; cursor: pointer; display: flex; align-items: center;"
onClick={(e: Event) => {
e.stopPropagation()
toggleColumnVisibility(col.key)
}}
>
<NCheckbox
checked={columnVisibility.value[col.key] !== false}
onUpdateChecked={() => toggleColumnVisibility(col.key)}
style="pointer-events: none;"
/>
<span style="margin-left: 8px; flex: 1;">{col.title || col.key}</span>
</div>
),
}
}),
{
key: 'divider2',
type: 'divider',
},
{
key: 'reset',
type: 'render',
render: () => (
<div
style="padding: 8px 12px; cursor: pointer; color: var(--n-color-target);"
onClick={() => resetColumnSettings()}
>
{hookT('resetColumns')}
</div>
),
},
]
return (
<NDropdown options={dropdownOptions} trigger="click" placement="bottom-end" showArrow={false}>
<NButton quaternary circle size="small" title={hookT('columnSettings')}>
<NIcon size={16}>
<svg viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M3 4H21V6H3V4ZM3 11H15V13H3V11ZM3 18H21V20H3V18Z" fill="currentColor" />
<path d="M16 11H18V13H16V11ZM19 11H21V13H19V11Z" fill="currentColor" />
</svg>
</NIcon>
</NButton>
</NDropdown>
)
}
// 检测到参数变化时,重新请求数据
if (Array.isArray(watchValue)) {
// 只监听指定的字段
@@ -225,10 +467,8 @@ export default function useTable<T = Record<string, any>, Z extends Record<strin
// 检查是否刚刚有直接请求,如果是则跳过此次 watch 触发的请求
const timeSinceLastDirectRequest = Date.now() - lastDirectRequestTime.value
if (timeSinceLastDirectRequest < REQUEST_DEBOUNCE_DELAY) {
console.log('跳过 watch 触发的重复请求,距离上次直接请求:', timeSinceLastDirectRequest, 'ms')
return
}
console.log('watch 触发请求,距离上次直接请求:', timeSinceLastDirectRequest, 'ms')
fetchData()
},
{ deep: true },
@@ -251,12 +491,19 @@ export default function useTable<T = Record<string, any>, Z extends Record<strin
fetch: fetchData<T>,
TableComponent: component,
PageComponent: paginationComponent,
ColumnSettingsComponent: columnSettingsComponent,
config: columns,
props,
storage,
handlePageChange,
handlePageSizeChange,
pageSizeOptions: pageSizeOptionsRef,
columnVisibility,
toggleColumnVisibility,
resetColumnSettings,
filteredColumns,
visibleColumnsWidth,
dynamicScrollX,
}
}) as TableInstanceWithComponent<T, Z>
}

View File

@@ -27,6 +27,11 @@ type TranslationTemplate = {
}
useTable: {
operation: string
columnSettings: string
showColumn: string
hideColumn: string
resetColumns: string
allColumns: string
}
}
@@ -80,6 +85,11 @@ export const translation = {
useTable: {
operation: '操作',
total: (total: number) => formatString('共 {} 条', total),
columnSettings: '列设置',
showColumn: '显示列',
hideColumn: '隐藏列',
resetColumns: '重置列设置',
allColumns: '全部列',
},
}),
zhTW: createTranslation({
@@ -142,6 +152,11 @@ export const translation = {
useTable: {
operation: 'Operation',
total: (total: number) => formatString('Total {} items', total),
columnSettings: 'Column Settings',
showColumn: 'Show Column',
hideColumn: 'Hide Column',
resetColumns: 'Reset Columns',
allColumns: 'All Columns',
},
}),
jaJP: createTranslation({

View File

@@ -1,6 +1,30 @@
import type { DataTableColumns, DataTableInst, DataTableProps } from 'naive-ui'
import type { Ref } from 'vue'
/** 列可见性配置接口 */
export interface ColumnVisibility {
/** 列的显示状态key为列的keyvalue为是否显示 */
[columnKey: string]: boolean
}
/** 列设置状态接口 */
export interface ColumnSettingsState {
/** 列可见性配置 */
visibility: ColumnVisibility
/** 表格唯一标识 */
tableId: string
}
/** 列设置组件属性接口 */
export interface ColumnSettingsProps {
/** 表格列配置 */
columns: DataTableColumns
/** 列可见性状态 */
visibility: ColumnVisibility
/** 可见性变更回调 */
onVisibilityChange: (visibility: ColumnVisibility) => void
}
/** 表格请求参数接口 */
export interface TableRequestParams {
/** 其他可能的查询参数 */
@@ -40,6 +64,8 @@ export interface TableInstanceWithComponent<T = Record<string, unknown>, Z = Rec
TableComponent: (props: Record<string, unknown>, context: Record<string, unknown>) => JSX.Element
/** 分页渲染组件用于渲染分页组件的Vue组件 */
PageComponent: (props: Record<string, unknown>, context: Record<string, unknown>) => JSX.Element
/** 列设置渲染组件用于渲染列设置下拉组件的Vue组件 */
ColumnSettingsComponent: () => JSX.Element
loading: Ref<boolean> // 加载状态
tableAlias: Ref<{ total: string; list: string }> // 表格别名
data: Ref<{ list: T[]; total: number }> // 表格数据引用
@@ -53,6 +79,12 @@ export interface TableInstanceWithComponent<T = Record<string, unknown>, Z = Rec
handlePageChange: (currentPage: number) => void // 分页改变
handlePageSizeChange: (size: number) => void // 分页大小改变
pageSizeOptions: Ref<number[]> // 分页大小选项
/** 列可见性状态 */
columnVisibility: Ref<ColumnVisibility>
/** 切换列可见性 */
toggleColumnVisibility: (columnKey: string) => void
/** 重置列设置 */
resetColumnSettings: () => void
}
/**

View File

@@ -2,6 +2,7 @@ import { defineComponent, ref, computed } from 'vue'
import { NSpace, NTabs, NTabPane, NBackTop, NButton } from 'naive-ui'
import TableDemo from './tabs/TableDemo'
import FormDemo from './tabs/FormDemo'
import ColumnSettingsDemo from './tabs/ColumnSettingsDemo'
import { useModal } from '../hooks/useModal'
// import FormBuilder from '../components/FormBuilder'
@@ -14,6 +15,8 @@ export default defineComponent({
return '动态表格'
} else if (tabName.value === 'form') {
return '动态表单'
} else if (tabName.value === 'column-settings') {
return '列设置功能'
} else if (tabName.value === 'builder') {
return '表单构建器'
}
@@ -41,6 +44,9 @@ export default defineComponent({
<NTabPane name="form" tab="动态表单">
<FormDemo />
</NTabPane>
<NTabPane name="column-settings" tab="列设置功能">
<ColumnSettingsDemo />
</NTabPane>
<NTabPane name="builder" tab="表单构建器">
{/* <FormBuilder /> */}
</NTabPane>

View File

@@ -208,6 +208,9 @@ importers:
autoprefixer:
specifier: ^10.4.20
version: 10.4.21(postcss@8.5.4)
cross-env:
specifier: ^7.0.3
version: 7.0.3
humps:
specifier: ^2.0.1
version: 2.0.1
@@ -4420,6 +4423,11 @@ packages:
create-require@1.1.1:
resolution: {integrity: sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ==}
cross-env@7.0.3:
resolution: {integrity: sha512-+/HKd6EgcQCJGh2PSjZuUitQBQynKor4wrFbRg4DtAgS1aWO+gU52xpH7M9ScGgXSYmAVS9bIJ8EzuaGw0oNAw==}
engines: {node: '>=10.14', npm: '>=6', yarn: '>=1'}
hasBin: true
cross-fetch@3.2.0:
resolution: {integrity: sha512-Q+xVJLoGOeIMXZmbUK4HYk+69cQH6LudR0Vu/pRm2YlU/hDV9CiS0gKUMaWY5f2NeUH9C1nV3bsTlCo0FsTV1Q==}
@@ -13182,6 +13190,10 @@ snapshots:
create-require@1.1.1: {}
cross-env@7.0.3:
dependencies:
cross-spawn: 7.0.6
cross-fetch@3.2.0:
dependencies:
node-fetch: 2.7.0

View File

@@ -5,8 +5,8 @@
<link rel="icon" href="./favicon.ico" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>AllinSSL</title>
<script type="module" crossorigin src="./static/js/main-1KUkgCjc.js"></script>
<link rel="stylesheet" crossorigin href="./static/css/style-CQp6NYrH.css">
<script type="module" crossorigin src="./static/js/main-BDlczVyX.js"></script>
<link rel="stylesheet" crossorigin href="./static/css/style-IFhjb5zS.css">
</head>
<body>
<div id="app"></div>

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1 @@
import{u as t}from"./index-DLsKoZLZ.js";import{d as s,c as o}from"./main-BDlczVyX.js";import"./useStore-DkzDjH23.js";import"./index-5v0IClw2.js";import"./access-D-zvf6ZM.js";import"./index-DXDdUjTY.js";import"./index-Bz5-OGyK.js";import"./throttle-N39ls_vw.js";import"./DownloadOutline-Bz5RohBy.js";import"./data-CWvQo6Gi.js";import"./index-CMXjHKrR.js";import"./business-Dpr0JUor.js";import"./index-CdEJrE2n.js";import"./text-I4DtFPsD.js";const e=s({name:"CAManageForm",props:{isEdit:{type:Boolean,default:!1},editId:{type:String,default:""}},setup(s){const{CAForm:e}=t(s);return()=>o(e,{labelPlacement:"top"},null)}});export{e as default};

View File

@@ -1 +0,0 @@
import{u as t}from"./index-DzBZsp2L.js";import{d as s,c as e}from"./main-1KUkgCjc.js";import"./useStore-BYMG6Fpb.js";import"./index-C7mXt0yr.js";import"./access-Xajiehoa.js";import"./index-DErbrG0I.js";import"./index-C4Kb3dVr.js";import"./throttle-CiEMydaW.js";import"./data-Cu_-2gKL.js";import"./index-CqYMVimh.js";import"./business-CulOz_oE.js";import"./index-B70Fb0s3.js";const o=s({name:"CAManageForm",props:{isEdit:{type:Boolean,default:!1},editId:{type:String,default:""}},setup(s){const{CAForm:o}=t(s);return()=>e(o,{labelPlacement:"top"},null)}});export{o as default};

View File

@@ -0,0 +1 @@
import{d as n,Y as o,Z as r,_ as e}from"./main-BDlczVyX.js";const t={xmlns:"http://www.w3.org/2000/svg","xmlns:xlink":"http://www.w3.org/1999/xlink",viewBox:"0 0 512 512"},l=n({name:"DownloadOutline",render:function(n,l){return r(),o("svg",t,l[0]||(l[0]=[e("path",{d:"M336 176h40a40 40 0 0 1 40 40v208a40 40 0 0 1-40 40H136a40 40 0 0 1-40-40V216a40 40 0 0 1 40-40h40",fill:"none",stroke:"currentColor","stroke-linecap":"round","stroke-linejoin":"round","stroke-width":"32"},null,-1),e("path",{fill:"none",stroke:"currentColor","stroke-linecap":"round","stroke-linejoin":"round","stroke-width":"32",d:"M176 272l80 80l80-80"},null,-1),e("path",{fill:"none",stroke:"currentColor","stroke-linecap":"round","stroke-linejoin":"round","stroke-width":"32",d:"M256 48v288"},null,-1)]))}});export{l as D};

View File

@@ -1 +1 @@
import{d as a,Y as l,Z as n,_ as r}from"./main-1KUkgCjc.js";const t={xmlns:"http://www.w3.org/2000/svg","xmlns:xlink":"http://www.w3.org/1999/xlink",viewBox:"0 0 20 20"},o=a({name:"Certificate20Regular",render:function(a,o){return n(),l("svg",t,o[0]||(o[0]=[r("g",{fill:"none"},[r("path",{d:"M2 5a2 2 0 0 1 2-2h12a2 2 0 0 1 2 2v3.146a4.508 4.508 0 0 0-1-.678V5a1 1 0 0 0-1-1H4a1 1 0 0 0-1 1v8a1 1 0 0 0 1 1h7.258c.076.113.157.223.242.329V15H4a2 2 0 0 1-2-2V5zm16.5 6.5c0 .954-.381 1.818-1 2.45V18a.5.5 0 0 1-.8.4l-1.4-1.05a.5.5 0 0 0-.6 0l-1.4 1.05a.5.5 0 0 1-.8-.4v-4.05a3.5 3.5 0 1 1 6-2.45zM15 15c-.537 0-1.045-.12-1.5-.337v2.087l1.243-.746a.5.5 0 0 1 .514 0l1.243.746v-2.087A3.486 3.486 0 0 1 15 15zm0-1a2.5 2.5 0 1 0 0-5a2.5 2.5 0 0 0 0 5zM5 6.5a.5.5 0 0 1 .5-.5h9a.5.5 0 0 1 0 1h-9a.5.5 0 0 1-.5-.5zm.5 4.5a.5.5 0 0 0 0 1h4a.5.5 0 0 0 0-1h-4z",fill:"currentColor"})],-1)]))}}),h={xmlns:"http://www.w3.org/2000/svg","xmlns:xlink":"http://www.w3.org/1999/xlink",viewBox:"0 0 32 32"},w=a({name:"CloudMonitoring",render:function(a,t){return n(),l("svg",h,t[0]||(t[0]=[r("path",{d:"M28 16v6H4V6h7V4H4a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h8v4H8v2h16v-2h-4v-4h8a2 2 0 0 0 2-2v-6zM18 28h-4v-4h4z",fill:"currentColor"},null,-1),r("path",{d:"M18 18h-.01a1 1 0 0 1-.951-.725L15.246 11H11V9h5a1 1 0 0 1 .962.725l1.074 3.76l3.009-9.78A1.014 1.014 0 0 1 22 3a.98.98 0 0 1 .949.684L24.72 9H30v2h-6a1 1 0 0 1-.949-.684l-1.013-3.04l-3.082 10.018A1 1 0 0 1 18 18z",fill:"currentColor"},null,-1)]))}}),v={xmlns:"http://www.w3.org/2000/svg","xmlns:xlink":"http://www.w3.org/1999/xlink",viewBox:"0 0 32 32"},e=a({name:"Flow",render:function(a,t){return n(),l("svg",v,t[0]||(t[0]=[r("path",{d:"M27 22.14V17a2 2 0 0 0-2-2h-8V9.86a4 4 0 1 0-2 0V15H7a2 2 0 0 0-2 2v5.14a4 4 0 1 0 2 0V17h18v5.14a4 4 0 1 0 2 0zM8 26a2 2 0 1 1-2-2a2 2 0 0 1 2 2zm6-20a2 2 0 1 1 2 2a2 2 0 0 1-2-2zm12 22a2 2 0 1 1 2-2a2 2 0 0 1-2 2z",fill:"currentColor"},null,-1)]))}});export{o as C,e as F,w as a};
import{d as a,Y as l,Z as n,_ as r}from"./main-BDlczVyX.js";const t={xmlns:"http://www.w3.org/2000/svg","xmlns:xlink":"http://www.w3.org/1999/xlink",viewBox:"0 0 20 20"},o=a({name:"Certificate20Regular",render:function(a,o){return n(),l("svg",t,o[0]||(o[0]=[r("g",{fill:"none"},[r("path",{d:"M2 5a2 2 0 0 1 2-2h12a2 2 0 0 1 2 2v3.146a4.508 4.508 0 0 0-1-.678V5a1 1 0 0 0-1-1H4a1 1 0 0 0-1 1v8a1 1 0 0 0 1 1h7.258c.076.113.157.223.242.329V15H4a2 2 0 0 1-2-2V5zm16.5 6.5c0 .954-.381 1.818-1 2.45V18a.5.5 0 0 1-.8.4l-1.4-1.05a.5.5 0 0 0-.6 0l-1.4 1.05a.5.5 0 0 1-.8-.4v-4.05a3.5 3.5 0 1 1 6-2.45zM15 15c-.537 0-1.045-.12-1.5-.337v2.087l1.243-.746a.5.5 0 0 1 .514 0l1.243.746v-2.087A3.486 3.486 0 0 1 15 15zm0-1a2.5 2.5 0 1 0 0-5a2.5 2.5 0 0 0 0 5zM5 6.5a.5.5 0 0 1 .5-.5h9a.5.5 0 0 1 0 1h-9a.5.5 0 0 1-.5-.5zm.5 4.5a.5.5 0 0 0 0 1h4a.5.5 0 0 0 0-1h-4z",fill:"currentColor"})],-1)]))}}),h={xmlns:"http://www.w3.org/2000/svg","xmlns:xlink":"http://www.w3.org/1999/xlink",viewBox:"0 0 32 32"},w=a({name:"CloudMonitoring",render:function(a,t){return n(),l("svg",h,t[0]||(t[0]=[r("path",{d:"M28 16v6H4V6h7V4H4a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h8v4H8v2h16v-2h-4v-4h8a2 2 0 0 0 2-2v-6zM18 28h-4v-4h4z",fill:"currentColor"},null,-1),r("path",{d:"M18 18h-.01a1 1 0 0 1-.951-.725L15.246 11H11V9h5a1 1 0 0 1 .962.725l1.074 3.76l3.009-9.78A1.014 1.014 0 0 1 22 3a.98.98 0 0 1 .949.684L24.72 9H30v2h-6a1 1 0 0 1-.949-.684l-1.013-3.04l-3.082 10.018A1 1 0 0 1 18 18z",fill:"currentColor"},null,-1)]))}}),v={xmlns:"http://www.w3.org/2000/svg","xmlns:xlink":"http://www.w3.org/1999/xlink",viewBox:"0 0 32 32"},e=a({name:"Flow",render:function(a,t){return n(),l("svg",v,t[0]||(t[0]=[r("path",{d:"M27 22.14V17a2 2 0 0 0-2-2h-8V9.86a4 4 0 1 0-2 0V15H7a2 2 0 0 0-2 2v5.14a4 4 0 1 0 2 0V17h18v5.14a4 4 0 1 0 2 0zM8 26a2 2 0 1 1-2-2a2 2 0 0 1 2 2zm6-20a2 2 0 1 1 2 2a2 2 0 0 1-2-2zm12 22a2 2 0 1 1 2-2a2 2 0 0 1-2 2z",fill:"currentColor"},null,-1)]))}});export{o as C,e as F,w as a};

View File

@@ -1 +1 @@
import{d as c,Y as n,Z as r,_ as t}from"./main-1KUkgCjc.js";const o={xmlns:"http://www.w3.org/2000/svg","xmlns:xlink":"http://www.w3.org/1999/xlink",viewBox:"0 0 1024 1024"},s=c({name:"LockOutlined",render:function(c,s){return r(),n("svg",o,s[0]||(s[0]=[t("path",{d:"M832 464h-68V240c0-70.7-57.3-128-128-128H388c-70.7 0-128 57.3-128 128v224h-68c-17.7 0-32 14.3-32 32v384c0 17.7 14.3 32 32 32h640c17.7 0 32-14.3 32-32V496c0-17.7-14.3-32-32-32zM332 240c0-30.9 25.1-56 56-56h248c30.9 0 56 25.1 56 56v224H332V240zm460 600H232V536h560v304zM484 701v53c0 4.4 3.6 8 8 8h40c4.4 0 8-3.6 8-8v-53a48.01 48.01 0 1 0-56 0z",fill:"currentColor"},null,-1)]))}});export{s as L};
import{d as c,Y as n,Z as r,_ as t}from"./main-BDlczVyX.js";const o={xmlns:"http://www.w3.org/2000/svg","xmlns:xlink":"http://www.w3.org/1999/xlink",viewBox:"0 0 1024 1024"},s=c({name:"LockOutlined",render:function(c,s){return r(),n("svg",o,s[0]||(s[0]=[t("path",{d:"M832 464h-68V240c0-70.7-57.3-128-128-128H388c-70.7 0-128 57.3-128 128v224h-68c-17.7 0-32 14.3-32 32v384c0 17.7 14.3 32 32 32h640c17.7 0 32-14.3 32-32V496c0-17.7-14.3-32-32-32zM332 240c0-30.9 25.1-56 56-56h248c30.9 0 56 25.1 56 56v224H332V240zm460 600H232V536h560v304zM484 701v53c0 4.4 3.6 8 8 8h40c4.4 0 8-3.6 8-8v-53a48.01 48.01 0 1 0-56 0z",fill:"currentColor"},null,-1)]))}});export{s as L};

View File

@@ -1 +1 @@
import{d as c,Y as a,Z as n,_ as o}from"./main-1KUkgCjc.js";const r={xmlns:"http://www.w3.org/2000/svg","xmlns:xlink":"http://www.w3.org/1999/xlink",viewBox:"0 0 512 512"},t=c({name:"LogoGithub",render:function(c,t){return n(),a("svg",r,t[0]||(t[0]=[o("path",{d:"M256 32C132.3 32 32 134.9 32 261.7c0 101.5 64.2 187.5 153.2 217.9a17.56 17.56 0 0 0 3.8.4c8.3 0 11.5-6.1 11.5-11.4c0-5.5-.2-19.9-.3-39.1a102.4 102.4 0 0 1-22.6 2.7c-43.1 0-52.9-33.5-52.9-33.5c-10.2-26.5-24.9-33.6-24.9-33.6c-19.5-13.7-.1-14.1 1.4-14.1h.1c22.5 2 34.3 23.8 34.3 23.8c11.2 19.6 26.2 25.1 39.6 25.1a63 63 0 0 0 25.6-6c2-14.8 7.8-24.9 14.2-30.7c-49.7-5.8-102-25.5-102-113.5c0-25.1 8.7-45.6 23-61.6c-2.3-5.8-10-29.2 2.2-60.8a18.64 18.64 0 0 1 5-.5c8.1 0 26.4 3.1 56.6 24.1a208.21 208.21 0 0 1 112.2 0c30.2-21 48.5-24.1 56.6-24.1a18.64 18.64 0 0 1 5 .5c12.2 31.6 4.5 55 2.2 60.8c14.3 16.1 23 36.6 23 61.6c0 88.2-52.4 107.6-102.3 113.3c8 7.1 15.2 21.1 15.2 42.5c0 30.7-.3 55.5-.3 63c0 5.4 3.1 11.5 11.4 11.5a19.35 19.35 0 0 0 4-.4C415.9 449.2 480 363.1 480 261.7C480 134.9 379.7 32 256 32z",fill:"currentColor"},null,-1)]))}});export{t as L};
import{d as c,Y as a,Z as n,_ as o}from"./main-BDlczVyX.js";const r={xmlns:"http://www.w3.org/2000/svg","xmlns:xlink":"http://www.w3.org/1999/xlink",viewBox:"0 0 512 512"},t=c({name:"LogoGithub",render:function(c,t){return n(),a("svg",r,t[0]||(t[0]=[o("path",{d:"M256 32C132.3 32 32 134.9 32 261.7c0 101.5 64.2 187.5 153.2 217.9a17.56 17.56 0 0 0 3.8.4c8.3 0 11.5-6.1 11.5-11.4c0-5.5-.2-19.9-.3-39.1a102.4 102.4 0 0 1-22.6 2.7c-43.1 0-52.9-33.5-52.9-33.5c-10.2-26.5-24.9-33.6-24.9-33.6c-19.5-13.7-.1-14.1 1.4-14.1h.1c22.5 2 34.3 23.8 34.3 23.8c11.2 19.6 26.2 25.1 39.6 25.1a63 63 0 0 0 25.6-6c2-14.8 7.8-24.9 14.2-30.7c-49.7-5.8-102-25.5-102-113.5c0-25.1 8.7-45.6 23-61.6c-2.3-5.8-10-29.2 2.2-60.8a18.64 18.64 0 0 1 5-.5c8.1 0 26.4 3.1 56.6 24.1a208.21 208.21 0 0 1 112.2 0c30.2-21 48.5-24.1 56.6-24.1a18.64 18.64 0 0 1 5 .5c12.2 31.6 4.5 55 2.2 60.8c14.3 16.1 23 36.6 23 61.6c0 88.2-52.4 107.6-102.3 113.3c8 7.1 15.2 21.1 15.2 42.5c0 30.7-.3 55.5-.3 63c0 5.4 3.1 11.5 11.4 11.5a19.35 19.35 0 0 0 4-.4C415.9 449.2 480 363.1 480 261.7C480 134.9 379.7 32 256 32z",fill:"currentColor"},null,-1)]))}});export{t as L};

File diff suppressed because one or more lines are too long

View File

@@ -1 +1 @@
import{c}from"./index-C7mXt0yr.js";const s=s=>c("/v1/access/get_list",s),a=s=>c("/v1/access/add_access",s),e=s=>c("/v1/access/upd_access",s),t=s=>c("/v1/access/del_access",s),_=s=>c("/v1/access/get_all",s),v=s=>c("/v1/acme_account/get_list",s),o=s=>c("/v1/acme_account/add_account",s),u=s=>c("/v1/acme_account/upd_account",s),d=s=>c("/v1/acme_account/del_account",s),n=s=>c("/v1/access/test_access",s),g=s=>c("/v1/access/get_sites",s),i=()=>c("/v1/access/get_plugins");export{a,i as b,v as c,t as d,o as e,u as f,s as g,d as h,g as i,_ as j,n as t,e as u};
import{c}from"./index-5v0IClw2.js";const s=s=>c("/v1/access/get_list",s),a=s=>c("/v1/access/add_access",s),e=s=>c("/v1/access/upd_access",s),t=s=>c("/v1/access/del_access",s),_=s=>c("/v1/access/get_all",s),v=s=>c("/v1/acme_account/get_list",s),o=s=>c("/v1/acme_account/add_account",s),u=s=>c("/v1/acme_account/upd_account",s),d=s=>c("/v1/acme_account/del_account",s),n=s=>c("/v1/access/test_access",s),g=s=>c("/v1/access/get_sites",s),i=()=>c("/v1/access/get_plugins");export{a,i as b,v as c,t as d,o as e,u as f,s as g,d as h,g as i,_ as j,n as t,e as u};

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@@ -1 +1 @@
import{$ as e}from"./main-1KUkgCjc.js";const t={mail:{name:e("t_68_1745289354676"),type:"mail"},workwx:{name:e("t_33_1746773350932"),type:"workwx"},dingtalk:{name:e("t_32_1746773348993"),type:"dingtalk"},feishu:{name:e("t_34_1746773350153"),type:"feishu"},webhook:{name:"WebHook",type:"webhook"}},n={zerossl:{name:"ZeroSSL",type:"zerossl"},google:{name:"Google",type:"google"},sslcom:{name:"SSL.COM",type:"sslcom"},buypass:{name:"Buypass",type:"buypass"},letsencrypt:{name:"Let's Encrypt",type:"letsencrypt"},custom:{name:"自定义",type:"custom"}},o={localhost:{name:e("t_4_1744958838951"),icon:"ssh",type:["host"],notApi:!1,hostRelated:{default:{name:e("t_4_1744958838951")}},sort:1},ssh:{name:"SSH",icon:"ssh",type:["host"],hostRelated:{default:{name:"SSH"}},sort:2},btpanel:{name:e("t_10_1745735765165"),icon:"btpanel",hostRelated:{default:{name:e("t_10_1745735765165")},site:{name:e("t_1_1747886307276")},dockersite:{name:e("t_0_1747994891459")},singlesite:{name:e("t_1_1747886307276")+"\r\nWin/Linux 9.4前)"}},type:["host"],sort:3},btwaf:{name:e("t_3_1747886302848"),icon:"btwaf",hostRelated:{site:{name:e("t_4_1747886303229")}},type:["host"],sort:4},"1panel":{name:"1Panel",icon:"1panel",hostRelated:{default:{name:"1Panel"},site:{name:e("t_2_1747886302053")}},type:["host"],sort:5},aliyun:{name:e("t_2_1747019616224"),icon:"aliyun",type:["host","dns"],hostRelated:{cdn:{name:e("t_16_1745735766712")},dcdn:{name:e("t_0_1752230148946")},oss:{name:e("t_2_1746697487164")},waf:{name:e("t_10_1744958860078")},esa:{name:e("t_1_1752230146379")}},sort:6},tencentcloud:{name:e("t_3_1747019616129"),icon:"tencentcloud",type:["host","dns"],hostRelated:{cdn:{name:e("t_14_1745735766121")},cos:{name:e("t_15_1745735768976")},waf:{name:e("t_9_1744958840634")},teo:{name:e("t_5_1747886301427")}},sort:7},huaweicloud:{name:e("t_9_1747886301128"),icon:"huaweicloud",type:["host","dns"],hostRelated:{cdn:{name:e("t_9_1747886301128")+"CDN"}},sort:10},baidu:{name:e("t_10_1747886300958"),icon:"baidu",type:["host","dns"],hostRelated:{cdn:{name:"百度云CDN"}},sort:11},volcengine:{name:e("t_13_1747886301689"),icon:"volcengine",type:["host","dns"],hostRelated:{cdn:{name:e("t_13_1747886301689")+"CDN"},dcdn:{name:e("t_13_1747886301689")+"DCDN"}},sort:13},safeline:{name:e("t_11_1747886301986"),icon:"safeline",type:["host"],hostRelated:{panel:{name:e("t_1_1747298114192")},site:{name:e("t_12_1747886302725")}},sort:8},qiniu:{name:e("t_6_1747886301844"),icon:"qiniu",type:["host"],hostRelated:{cdn:{name:e("t_7_1747886302395")},oss:{name:e("t_8_1747886304014")}},sort:9},cloudflare:{name:"Cloudflare",icon:"cloudflare",type:["dns"],sort:12},westcn:{name:e("t_14_1747886301884"),icon:"westcn",type:["dns"],sort:14},godaddy:{name:"GoDaddy",icon:"godaddy",type:["dns"],sort:15},namecheap:{name:"Namecheap",icon:"namecheap",type:["dns"],sort:16},ns1:{name:"NS1",icon:"ns1",type:["dns"],sort:17},cloudns:{name:"ClouDNS",icon:"cloudns",type:["dns"],sort:18},aws:{name:"AWS",icon:"aws",type:["dns"],sort:19},azure:{name:"Azure",icon:"azure",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},lecdn:{name:"LeCDN",icon:"lecdn",type:["dns","host"],hostRelated:{default:{name:"LeCDN"}},sort:26},constellix:{name:"Constellix",icon:"constellix",type:["dns"],sort:27},doge:{name:e("t_0_1750129254226"),icon:"doge",type:["host"],hostRelated:{cdn:{name:e("t_0_1750129254226")+"CDN"}},sort:28},plugin:{name:"插件",icon:"plugin",type:["host"],hostRelated:{default:{name:"插件"}},sort:29}};export{o as A,n as C,t as M};
import{$ as e}from"./main-BDlczVyX.js";const t={mail:{name:e("t_68_1745289354676"),type:"mail"},workwx:{name:e("t_33_1746773350932"),type:"workwx"},dingtalk:{name:e("t_32_1746773348993"),type:"dingtalk"},feishu:{name:e("t_34_1746773350153"),type:"feishu"},webhook:{name:"WebHook",type:"webhook"}},n={zerossl:{name:"ZeroSSL",type:"zerossl"},google:{name:"Google",type:"google"},sslcom:{name:"SSL.COM",type:"sslcom"},buypass:{name:"Buypass",type:"buypass"},letsencrypt:{name:"Let's Encrypt",type:"letsencrypt"},custom:{name:"自定义",type:"custom"}},o={localhost:{name:e("t_4_1744958838951"),icon:"ssh",type:["host"],notApi:!1,hostRelated:{default:{name:e("t_4_1744958838951")}},sort:1},ssh:{name:"SSH",icon:"ssh",type:["host"],hostRelated:{default:{name:"SSH"}},sort:2},btpanel:{name:e("t_10_1745735765165"),icon:"btpanel",hostRelated:{default:{name:e("t_10_1745735765165")},site:{name:e("t_1_1747886307276")},dockersite:{name:e("t_0_1747994891459")},singlesite:{name:e("t_1_1747886307276")+"\r\nWin/Linux 9.4前)"}},type:["host"],sort:3},btwaf:{name:e("t_3_1747886302848"),icon:"btwaf",hostRelated:{site:{name:e("t_4_1747886303229")}},type:["host"],sort:4},"1panel":{name:"1Panel",icon:"1panel",hostRelated:{default:{name:"1Panel"},site:{name:e("t_2_1747886302053")}},type:["host"],sort:5},aliyun:{name:e("t_2_1747019616224"),icon:"aliyun",type:["host","dns"],hostRelated:{cdn:{name:e("t_16_1745735766712")},dcdn:{name:e("t_0_1752230148946")},oss:{name:e("t_2_1746697487164")},waf:{name:e("t_10_1744958860078")},esa:{name:e("t_1_1752230146379")}},sort:6},tencentcloud:{name:e("t_3_1747019616129"),icon:"tencentcloud",type:["host","dns"],hostRelated:{cdn:{name:e("t_14_1745735766121")},cos:{name:e("t_15_1745735768976")},waf:{name:e("t_9_1744958840634")},teo:{name:e("t_5_1747886301427")}},sort:7},huaweicloud:{name:e("t_9_1747886301128"),icon:"huaweicloud",type:["host","dns"],hostRelated:{cdn:{name:e("t_9_1747886301128")+"CDN"}},sort:10},baidu:{name:e("t_10_1747886300958"),icon:"baidu",type:["host","dns"],hostRelated:{cdn:{name:"百度云CDN"}},sort:11},volcengine:{name:e("t_13_1747886301689"),icon:"volcengine",type:["host","dns"],hostRelated:{cdn:{name:e("t_13_1747886301689")+"CDN"},dcdn:{name:e("t_13_1747886301689")+"DCDN"}},sort:13},safeline:{name:e("t_11_1747886301986"),icon:"safeline",type:["host"],hostRelated:{panel:{name:e("t_1_1747298114192")},site:{name:e("t_12_1747886302725")}},sort:8},qiniu:{name:e("t_6_1747886301844"),icon:"qiniu",type:["host"],hostRelated:{cdn:{name:e("t_7_1747886302395")},oss:{name:e("t_8_1747886304014")}},sort:9},cloudflare:{name:"Cloudflare",icon:"cloudflare",type:["dns"],sort:12},westcn:{name:e("t_14_1747886301884"),icon:"westcn",type:["dns"],sort:14},godaddy:{name:"GoDaddy",icon:"godaddy",type:["dns"],sort:15},namecheap:{name:"Namecheap",icon:"namecheap",type:["dns"],sort:16},ns1:{name:"NS1",icon:"ns1",type:["dns"],sort:17},cloudns:{name:"ClouDNS",icon:"cloudns",type:["dns"],sort:18},aws:{name:"AWS",icon:"aws",type:["dns"],sort:19},azure:{name:"Azure",icon:"azure",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},lecdn:{name:"LeCDN",icon:"lecdn",type:["dns","host"],hostRelated:{default:{name:"LeCDN"}},sort:26},constellix:{name:"Constellix",icon:"constellix",type:["dns"],sort:27},doge:{name:e("t_0_1750129254226"),icon:"doge",type:["host"],hostRelated:{cdn:{name:e("t_0_1750129254226")+"CDN"}},sort:28},plugin:{name:"插件",icon:"plugin",type:["host"],hostRelated:{default:{name:"插件"}},sort:29}};export{o as A,n as C,t as M};

View File

@@ -1 +1 @@
import{_ as e,c as t}from"./index-C7mXt0yr.js";import{bk as r,bp as n,bH as a,bx as u,bI as s}from"./main-1KUkgCjc.js";function o(e,t,r){for(var n=0,a=r.length;n<a;){if((t=e["@@transducer/step"](t,r[n]))&&t["@@transducer/reduced"]){t=t["@@transducer/value"];break}n+=1}return e["@@transducer/result"](t)}var c=r((function(e,t){return n(e.length,(function(){return e.apply(t,arguments)}))}));function i(e,t,r){for(var n=r.next();!n.done;){if((t=e["@@transducer/step"](t,n.value))&&t["@@transducer/reduced"]){t=t["@@transducer/value"];break}n=r.next()}return e["@@transducer/result"](t)}function d(e,t,r,n){return e["@@transducer/result"](r[n](c(e["@@transducer/step"],e),t))}var g=a(o,d,i),f=function(){function e(e){this.f=e}return e.prototype["@@transducer/init"]=function(){throw new Error("init not implemented on XWrap")},e.prototype["@@transducer/result"]=function(e){return e},e.prototype["@@transducer/step"]=function(e,t){return this.f(e,t)},e}();function l(e){return new f(e)}var p=e((function(e,t,r){return g("function"==typeof e?l(e):e,t,r)})),m=r((function(e,t){for(var r=0,n=Math.min(e.length,t.length),a={};r<n;)a[e[r]]=t[r],r+=1;return a}));const y=e=>t("/v1/cert/get_list",e),D=e=>t("/v1/cert/upload_cert",e),w=e=>t("/v1/cert/del_cert",e),h=(e,t="yyyy-MM-dd HH:mm:ss")=>{const r=Number(e)&&10===e.toString().length?new Date(1e3*Number(e)):new Date(e),n=m(["yyyy","MM","dd","HH","mm","ss"],[r.getFullYear(),r.getMonth()+1,r.getDate(),r.getHours(),r.getMinutes(),r.getSeconds()]);return p(((e,t)=>{const r=n[t],a="yyyy"!==t&&r<10?`0${r}`:`${r}`;return e.replace(new RegExp(t,"g"),a)}),t,s(n))},v=(e,t)=>{const r=new Date(e),n=new Date(t),a=new Date(r.getFullYear(),r.getMonth(),r.getDate()),u=new Date(n.getFullYear(),n.getMonth(),n.getDate()).getTime()-a.getTime();return Math.floor(u/864e5)};u(v);u(((e,t,r)=>{const n=new Date(e).getTime(),a=new Date(t).getTime(),u=new Date(r).getTime();return n>=a&&n<=u}));u(((e,t)=>{const r=new Date(t);return r.setDate(r.getDate()+e),r}));export{g as _,l as a,h as c,w as d,y as g,v as i,p as r,D as u};
import{_ as e,c as t}from"./index-5v0IClw2.js";import{bn as r,bs as n,bJ as a,bA as u,bK as s}from"./main-BDlczVyX.js";function o(e,t,r){for(var n=0,a=r.length;n<a;){if((t=e["@@transducer/step"](t,r[n]))&&t["@@transducer/reduced"]){t=t["@@transducer/value"];break}n+=1}return e["@@transducer/result"](t)}var c=r((function(e,t){return n(e.length,(function(){return e.apply(t,arguments)}))}));function i(e,t,r){for(var n=r.next();!n.done;){if((t=e["@@transducer/step"](t,n.value))&&t["@@transducer/reduced"]){t=t["@@transducer/value"];break}n=r.next()}return e["@@transducer/result"](t)}function d(e,t,r,n){return e["@@transducer/result"](r[n](c(e["@@transducer/step"],e),t))}var g=a(o,d,i),f=function(){function e(e){this.f=e}return e.prototype["@@transducer/init"]=function(){throw new Error("init not implemented on XWrap")},e.prototype["@@transducer/result"]=function(e){return e},e.prototype["@@transducer/step"]=function(e,t){return this.f(e,t)},e}();function l(e){return new f(e)}var p=e((function(e,t,r){return g("function"==typeof e?l(e):e,t,r)})),m=r((function(e,t){for(var r=0,n=Math.min(e.length,t.length),a={};r<n;)a[e[r]]=t[r],r+=1;return a}));const y=e=>t("/v1/cert/get_list",e),D=e=>t("/v1/cert/upload_cert",e),w=e=>t("/v1/cert/del_cert",e),h=(e,t="yyyy-MM-dd HH:mm:ss")=>{const r=Number(e)&&10===e.toString().length?new Date(1e3*Number(e)):new Date(e),n=m(["yyyy","MM","dd","HH","mm","ss"],[r.getFullYear(),r.getMonth()+1,r.getDate(),r.getHours(),r.getMinutes(),r.getSeconds()]);return p(((e,t)=>{const r=n[t],a="yyyy"!==t&&r<10?`0${r}`:`${r}`;return e.replace(new RegExp(t,"g"),a)}),t,s(n))},v=(e,t)=>{const r=new Date(e),n=new Date(t),a=new Date(r.getFullYear(),r.getMonth(),r.getDate()),u=new Date(n.getFullYear(),n.getMonth(),n.getDate()).getTime()-a.getTime();return Math.floor(u/864e5)};u(v);u(((e,t,r)=>{const n=new Date(e).getTime(),a=new Date(t).getTime(),u=new Date(r).getTime();return n>=a&&n<=u}));u(((e,t)=>{const r=new Date(t);return r.setDate(r.getDate()+e),r}));export{g as _,l as a,h as c,w as d,y as g,v as i,p as r,D as u};

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@@ -1 +0,0 @@
var t;import{S as e}from"./index-CqYMVimh.js";import{A as o,M as a}from"./data-Cu_-2gKL.js";import{k as n,d as s,c as i,N as l}from"./main-1KUkgCjc.js";const r={},p={},c=new Set;for(const d in o)if(Object.prototype.hasOwnProperty.call(o,d)){const e=o[d];if(r[d]=e.name,p[d]=e.icon,null==e?void 0:e.hostRelated)for(const o in e.hostRelated)if(Object.prototype.hasOwnProperty.call(e.hostRelated,o)){const a=e.hostRelated[o],n=`${d}-${o}`;n&&(r[n]=(null==(t=null==a?void 0:a.name)?void 0:t.toString())??"",p[n]=e.icon)}}for(const d in a)if(Object.prototype.hasOwnProperty.call(a,d)){const t=a[d];r[d]=t.name,p[d]=t.type,c.add(d)}o.btwaf&&(p.btwaf="btpanel");const u=s({name:"AuthApiTypeIcon",props:{icon:{type:String,required:!0},type:{type:String,default:"default"},text:{type:Boolean,default:!0}},setup(t){const{iconPath:o,typeName:a}=function(t){return{iconPath:n((()=>(c.has(t.icon)?"notify-":"resources-")+(p[t.icon]||"default"))),typeName:n((()=>r[t.icon]||t.icon))}}(t);return()=>i(l,{type:t.type,size:"small",class:"w-auto text-ellipsis overflow-hidden whitespace-normal p-[.6rem] h-auto"},{default:()=>[i(e,{icon:o.value,size:"1.2rem",class:"mr-[0.4rem]"},null),i("span",null,[t.text&&i("span",{class:"text-[12px]"},[a.value])])]})}});export{u as T};

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1 @@
var t;import{S as e}from"./index-CMXjHKrR.js";import{A as a,M as o}from"./data-CWvQo6Gi.js";import{k as r,d as n,c as s,N as i,i as l}from"./main-BDlczVyX.js";import{N as c}from"./business-Dpr0JUor.js";const p={},m={},y=new Set;for(const f in a)if(Object.prototype.hasOwnProperty.call(a,f)){const e=a[f];if(p[f]=e.name,m[f]=e.icon,null==e?void 0:e.hostRelated)for(const a in e.hostRelated)if(Object.prototype.hasOwnProperty.call(e.hostRelated,a)){const o=e.hostRelated[a],r=`${f}-${a}`;r&&(p[r]=(null==(t=null==o?void 0:o.name)?void 0:t.toString())??"",m[r]=e.icon)}}for(const f in o)if(Object.prototype.hasOwnProperty.call(o,f)){const t=o[f];p[f]=t.name,m[f]=t.type,y.add(f)}a.btwaf&&(m.btwaf="btpanel");const u=n({name:"AuthApiTypeIcon",props:{icon:{type:[String,Array],required:!0},type:{type:String,default:"default"},text:{type:Boolean,default:!0}},setup(t){const{iconPath:a,typeName:o,iconItems:n}=function(t){return{iconPath:r((()=>{const e=Array.isArray(t.icon)?t.icon[0]:t.icon;return e?(y.has(e)?"notify-":"resources-")+(m[e]||"default"):"resources-default"})),typeName:r((()=>Array.isArray(t.icon)?t.icon.filter(Boolean).map((t=>p[t]||t)).join(", "):p[t.icon]||t.icon)),iconItems:r((()=>(Array.isArray(t.icon)?t.icon:[t.icon]).filter(Boolean).map((t=>({iconPath:(y.has(t)?"notify-":"resources-")+(m[t]||"default"),typeName:p[t]||t,key:t})))))}}(t);return()=>{if(Array.isArray(t.icon)&&t.icon.length>1){let a;return s(c,{size:"small",wrap:!0,style:"gap: 4px; flex-wrap: wrap;"},"function"==typeof(r=a=n.value.map(((a,o)=>s(i,{key:a.key,type:t.type,size:"small",class:"w-auto text-ellipsis overflow-hidden whitespace-normal p-[.6rem] h-auto mb-1",style:"margin-right: 4px; max-width: 100%;"},{default:()=>[s(e,{icon:a.iconPath,size:"1.2rem",class:"mr-[0.4rem] flex-shrink-0"},null),t.text&&s("span",{class:"text-[12px] truncate"},[a.typeName])]}))))||"[object Object]"===Object.prototype.toString.call(r)&&!l(r)?a:{default:()=>[a]})}var r;return s(i,{type:t.type,size:"small",class:"w-auto text-ellipsis overflow-hidden whitespace-normal p-[.6rem] h-auto",style:"max-width: 100%;"},{default:()=>[s(e,{icon:a.value,size:"1.2rem",class:"mr-[0.4rem] flex-shrink-0"},null),t.text&&s("span",{class:"text-[12px] truncate"},[o.value])]})}}});export{u as T};

File diff suppressed because one or more lines are too long

View File

@@ -1 +1 @@
import{d as e,u as t,a as o,c as r,b as s,$ as l,B as a,i as c}from"./main-1KUkgCjc.js";const m=(e=16,t)=>r("svg",{width:e,height:e,viewBox:"0 0 16 16",xmlns:"http://www.w3.org/2000/svg",fill:t},[r("path",{"fill-rule":"evenodd","clip-rule":"evenodd",d:"M8.6 1c1.6.1 3.1.9 4.2 2 1.3 1.4 2 3.1 2 5.1 0 1.6-.6 3.1-1.6 4.4-1 1.2-2.4 2.1-4 2.4-1.6.3-3.2.1-4.6-.7-1.4-.8-2.5-2-3.1-3.5C.9 9.2.8 7.5 1.3 6c.5-1.6 1.4-2.9 2.8-3.8C5.4 1.3 7 .9 8.6 1zm.5 12.9c1.3-.3 2.5-1 3.4-2.1.8-1.1 1.3-2.4 1.2-3.8 0-1.6-.6-3.2-1.7-4.3-1-1-2.2-1.6-3.6-1.7-1.3-.1-2.7.2-3.8 1-1.1.8-1.9 1.9-2.3 3.3-.4 1.3-.4 2.7.2 4 .6 1.3 1.5 2.3 2.7 3 1.2.7 2.6.9 3.9.6zM7.9 7.5L10.3 5l.7.7-2.4 2.5 2.4 2.5-.7.7-2.4-2.5-2.4 2.5-.7-.7 2.4-2.5-2.4-2.5.7-.7 2.4 2.5z"},null)]),n=e({setup(){const e=t(),n=o(["baseColor","textColorBase","textColorSecondary","textColorDisabled"]);return()=>{let t;return r("div",{class:"flex flex-col items-center justify-center min-h-screen p-4",style:n.value},[r("div",{class:"text-center px-4 sm:px-8 max-w-[60rem] mx-auto"},[r("div",{class:"text-[4.5rem] sm:text-[6rem] md:text-[8rem] font-bold leading-none mb-2 sm:mb-4",style:{color:"var(--n-text-color-base)",textShadow:"2px 2px 8px rgba(0,0,0,0.25)"}},[s("404")]),r("div",{class:"flex items-center justify-center mb-4 sm:mb-8"},[m(60,"var(--n-text-color-base)")]),r("div",{class:"text-[1.2rem] sm:text-[1.5rem] md:text-[1.8rem] mb-4 sm:mb-8",style:{color:"var(--n-text-color-secondary)"}},[l("t_0_1744098811152")]),r(a,{style:{backgroundColor:"var(--n-text-color-base)",color:"var(--n-base-color)",border:"none"},onClick:()=>e.push("/")},(o=t=l("t_1_1744098801860"),"function"==typeof o||"[object Object]"===Object.prototype.toString.call(o)&&!c(o)?t:{default:()=>[t]})),r("div",{class:"mt-4 sm:mt-8 text-[1rem] sm:text-[1.1rem] md:text-[1.3rem]",style:{color:"var(--n-text-color-disabled)"}},[l("t_2_1744098804908")])])]);var o}}});export{n as default};
import{d as e,u as t,a as o,c as r,b as s,$ as l,B as a,i as c}from"./main-BDlczVyX.js";const m=(e=16,t)=>r("svg",{width:e,height:e,viewBox:"0 0 16 16",xmlns:"http://www.w3.org/2000/svg",fill:t},[r("path",{"fill-rule":"evenodd","clip-rule":"evenodd",d:"M8.6 1c1.6.1 3.1.9 4.2 2 1.3 1.4 2 3.1 2 5.1 0 1.6-.6 3.1-1.6 4.4-1 1.2-2.4 2.1-4 2.4-1.6.3-3.2.1-4.6-.7-1.4-.8-2.5-2-3.1-3.5C.9 9.2.8 7.5 1.3 6c.5-1.6 1.4-2.9 2.8-3.8C5.4 1.3 7 .9 8.6 1zm.5 12.9c1.3-.3 2.5-1 3.4-2.1.8-1.1 1.3-2.4 1.2-3.8 0-1.6-.6-3.2-1.7-4.3-1-1-2.2-1.6-3.6-1.7-1.3-.1-2.7.2-3.8 1-1.1.8-1.9 1.9-2.3 3.3-.4 1.3-.4 2.7.2 4 .6 1.3 1.5 2.3 2.7 3 1.2.7 2.6.9 3.9.6zM7.9 7.5L10.3 5l.7.7-2.4 2.5 2.4 2.5-.7.7-2.4-2.5-2.4 2.5-.7-.7 2.4-2.5-2.4-2.5.7-.7 2.4 2.5z"},null)]),n=e({setup(){const e=t(),n=o(["baseColor","textColorBase","textColorSecondary","textColorDisabled"]);return()=>{let t;return r("div",{class:"flex flex-col items-center justify-center min-h-screen p-4",style:n.value},[r("div",{class:"text-center px-4 sm:px-8 max-w-[60rem] mx-auto"},[r("div",{class:"text-[4.5rem] sm:text-[6rem] md:text-[8rem] font-bold leading-none mb-2 sm:mb-4",style:{color:"var(--n-text-color-base)",textShadow:"2px 2px 8px rgba(0,0,0,0.25)"}},[s("404")]),r("div",{class:"flex items-center justify-center mb-4 sm:mb-8"},[m(60,"var(--n-text-color-base)")]),r("div",{class:"text-[1.2rem] sm:text-[1.5rem] md:text-[1.8rem] mb-4 sm:mb-8",style:{color:"var(--n-text-color-secondary)"}},[l("t_0_1744098811152")]),r(a,{style:{backgroundColor:"var(--n-text-color-base)",color:"var(--n-base-color)",border:"none"},onClick:()=>e.push("/")},(o=t=l("t_1_1744098801860"),"function"==typeof o||"[object Object]"===Object.prototype.toString.call(o)&&!c(o)?t:{default:()=>[t]})),r("div",{class:"mt-4 sm:mt-8 text-[1rem] sm:text-[1.1rem] md:text-[1.3rem]",style:{color:"var(--n-text-color-disabled)"}},[l("t_2_1744098804908")])])]);var o}}});export{n as default};

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@@ -1 +1 @@
import{d as e,c as s}from"./main-1KUkgCjc.js";const l=e({name:"BaseComponent",setup(e,{slots:l}){const t=l["header-left"]||l.headerLeft,f=l["header-right"]||l.headerRight,r=l.header,o=l["footer-left"]||l.footerLeft,a=l["footer-right"]||l.footerRight,i=l.footer;return()=>s("div",{class:"flex flex-col"},[r?s("div",{class:"flex justify-between flex-wrap w-full"},[r()]):(t||f)&&s("div",{class:"flex justify-between flex-wrap",style:{rowGap:"0.8rem"}},[s("div",{class:"flex flex-shrink-0"},[t&&t()]),s("div",{class:"flex flex-shrink-0"},[f&&f()])]),s("div",{class:`w-full content ${r||t||f?"mt-[1.2rem]":""} ${i||o||a?"mb-[1.2rem]":""}`},[l.content&&l.content()]),i?s("div",{class:"flex justify-between w-full"},[i()]):(o||a)&&s("div",{class:"flex justify-between"},[s("div",{class:"flex flex-shrink-0"},[o&&o()]),s("div",{class:"flex flex-shrink-0"},[a&&a()])]),l.popup&&l.popup()])}});export{l as B};
import{d as e,c as s}from"./main-BDlczVyX.js";const l=e({name:"BaseComponent",setup(e,{slots:l}){const t=l["header-left"]||l.headerLeft,f=l["header-right"]||l.headerRight,r=l.header,o=l["footer-left"]||l.footerLeft,a=l["footer-right"]||l.footerRight,i=l.footer;return()=>s("div",{class:"flex flex-col"},[r?s("div",{class:"flex justify-between flex-wrap w-full"},[r()]):(t||f)&&s("div",{class:"flex justify-between flex-wrap",style:{rowGap:"0.8rem"}},[s("div",{class:"flex flex-shrink-0"},[t&&t()]),s("div",{class:"flex flex-shrink-0"},[f&&f()])]),s("div",{class:`w-full content ${r||t||f?"mt-[1.2rem]":""} ${i||o||a?"mb-[1.2rem]":""}`},[l.content&&l.content()]),i?s("div",{class:"flex justify-between w-full"},[i()]):(o||a)&&s("div",{class:"flex justify-between"},[s("div",{class:"flex flex-shrink-0"},[o&&o()]),s("div",{class:"flex flex-shrink-0"},[a&&a()])]),l.popup&&l.popup()])}});export{l as B};

File diff suppressed because one or more lines are too long

View File

@@ -1 +1 @@
import{d as e,k as i,c as r}from"./main-1KUkgCjc.js";const t=e({name:"SvgIcon",props:{icon:{type:String,required:!0},color:{type:String,default:""},size:{type:String,default:"1.8rem"}},setup(e){const t=i((()=>`#icon-${e.icon}`));return()=>r("svg",{class:"relative inline-block align-[-0.2rem]",style:{width:e.size,height:e.size},"aria-hidden":"true"},[r("use",{"xlink:href":t.value,fill:e.color},null)])}});export{t as S};
import{d as e,k as i,c as r}from"./main-BDlczVyX.js";const t=e({name:"SvgIcon",props:{icon:{type:String,required:!0},color:{type:String,default:""},size:{type:String,default:"1.8rem"}},setup(e){const t=i((()=>`#icon-${e.icon}`));return()=>r("svg",{class:"relative inline-block align-[-0.2rem]",style:{width:e.size,height:e.size},"aria-hidden":"true"},[r("use",{"xlink:href":t.value,fill:e.color},null)])}});export{t as S};

View File

@@ -0,0 +1 @@
import{u as e}from"./useStore-BEQER5Bu.js";import{u as a,N as l}from"./index-5v0IClw2.js";import{r as t,x as u,o as v,aD as s,$ as d,d as r,c as o,w as n,t as i,m as p,B as y,i as c}from"./main-BDlczVyX.js";import{S as f}from"./index-CMXjHKrR.js";import{N as m}from"./text-I4DtFPsD.js";import{N as b}from"./business-Dpr0JUor.js";const _=r({name:"DnsProviderSelect",props:{type:{type:String,required:!0},path:{type:String,required:!0},value:{type:String,required:!0},valueType:{type:String,default:"value"},isAddMode:{type:Boolean,default:!0},disabled:{type:Boolean,default:!1},customClass:{type:String,default:""}},emits:["update:value"],setup(r,{emit:_}){const g=function(l,r){const{handleError:o}=a(),{fetchDnsProvider:n,resetDnsProvider:i,dnsProvider:p}=e(),y=t({label:"",value:"",type:"",data:{}}),c=t([]),f=t(!1),m=t(""),b=()=>{var e,a,t,u,v;const s=p.value.find((e=>("value"===l.valueType?e.value:e.type)===y.value.value));s?(y.value={label:s.label,value:"value"===l.valueType?s.value:s.type,type:"value"===l.valueType?s.type:s.value,data:s},r("update:value",{...y.value})):""===y.value.value&&p.value.length>0&&(y.value={label:(null==(e=p.value[0])?void 0:e.label)||"",value:"value"===l.valueType?(null==(a=p.value[0])?void 0:a.value)||"":(null==(t=p.value[0])?void 0:t.type)||"",type:"value"===l.valueType?(null==(u=p.value[0])?void 0:u.type)||"":(null==(v=p.value[0])?void 0:v.value)||"",data:p.value[0]||{}},r("update:value",{...y.value}))},_=e=>{y.value.value=e,b()},g=async(e=l.type)=>{f.value=!0,m.value="";try{await n(e),l.value?(y.value.value=l.value,b()):b()}catch(a){m.value="string"==typeof a?a:d("t_0_1746760933542"),o(a)}finally{f.value=!1}};return u((()=>p.value),(e=>{var a;c.value=e.map((e=>({label:e.label,value:"value"===l.valueType?e.value:e.type,type:"value"===l.valueType?e.type:e.value,data:e})))||[],c.value.some((e=>e.value===y.value.value))?b():l.value&&c.value.some((e=>e.value===l.value))?(y.value.value=l.value,b()):""===y.value.value&&c.value.length>0&&(y.value.value=(null==(a=c.value[0])?void 0:a.value)||"",b())}),{deep:!0}),u((()=>l.value),(e=>{e!==y.value.value&&_(e)}),{immediate:!0}),u((()=>l.type),(e=>{g(e)})),v((async()=>{await g(l.type)})),s((()=>{i()})),{param:y,dnsProviderRef:c,isLoading:f,errorMessage:m,goToAddDnsProvider:()=>{window.open("/auth-api-manage","_blank")},handleUpdateValue:_,loadDnsProviders:g,handleFilter:(e,a)=>a.label.toLowerCase().includes(e.toLowerCase())}}(r,_),h=e=>o(b,{align:"center"},{default:()=>[o(f,{icon:`resources-${e.type}`,size:"2rem"},null),o(m,null,{default:()=>[e.label]})]});return()=>{let e;return o(l,{show:g.isLoading.value},{default:()=>[o(n,{cols:24,class:r.customClass},{default:()=>[o(i,{span:r.isAddMode?13:24,label:"dns"===r.type?d("t_3_1745735765112"):d("t_0_1746754500246"),path:r.path},{default:()=>[o(p,{class:"flex-1 w-full",filterable:!0,options:g.dnsProviderRef.value,renderLabel:h,renderTag:({option:e})=>(({option:e})=>o(b,{align:"center"},{default:()=>[e.label?h(e):o(m,{class:"text-[#aaa]"},{default:()=>["dns"===r.type?d("t_0_1747019621052"):d("t_0_1746858920894")]})]}))({option:e}),filter:(e,a)=>g.handleFilter(e,a),placeholder:"dns"===r.type?d("t_3_1745490735059"):d("t_0_1746858920894"),value:g.param.value.value,onUpdateValue:g.handleUpdateValue,disabled:r.disabled},{empty:()=>o("span",{class:"text-[1.4rem]"},[g.errorMessage.value||("dns"===r.type?d("t_1_1746858922914"):d("t_2_1746858923964"))])})]}),r.isAddMode&&o(i,{span:11},{default:()=>{return[o(y,{class:"mx-[8px]",onClick:g.goToAddDnsProvider,disabled:r.disabled},{default:()=>["dns"===r.type?d("t_1_1746004861166"):d("t_3_1746858920060")]}),o(y,{onClick:()=>g.loadDnsProviders(r.type),loading:g.isLoading.value,disabled:r.disabled},(a=e=d("t_0_1746497662220"),"function"==typeof a||"[object Object]"===Object.prototype.toString.call(a)&&!c(a)?e:{default:()=>[e]}))];var a}})]})]})}}});export{_ as D};

View File

@@ -1 +1 @@
import{p as e,i as t,b as n,t as a,w as r,c as o,d as l,e as s,f as i}from"./index-B70Fb0s3.js";import{bS as u,av as f,bT as c,k as d,bU as v,o as g,bV as p,bW as w,r as m,x as y,V as h}from"./main-1KUkgCjc.js";const b=n?window:void 0;function S(...e){const t=[],n=()=>{t.forEach((e=>e())),t.length=0},s=d((()=>{const t=a(c(e[0])).filter((e=>null!=e));return t.every((e=>"string"!=typeof e))?t:void 0})),i=r((()=>{var t,n;return[null!=(n=null==(t=s.value)?void 0:t.map((e=>function(e){var t;const n=c(e);return null!=(t=null==n?void 0:n.$el)?t:n}(e))))?n:[b].filter((e=>null!=e)),a(c(s.value?e[1]:e[0])),a(w(s.value?e[2]:e[1])),c(s.value?e[3]:e[2])]}),(([e,a,r,o])=>{if(n(),!(null==e?void 0:e.length)||!(null==a?void 0:a.length)||!(null==r?void 0:r.length))return;const s=l(o)?{...o}:o;t.push(...e.flatMap((e=>a.flatMap((t=>r.map((n=>((e,t,n,a)=>(e.addEventListener(t,n,a),()=>e.removeEventListener(t,n,a)))(e,t,n,s))))))))}),{flush:"post"});return o(n),()=>{i(),n()}}function N(e){const t=function(){const e=u(!1),t=p();return t&&g((()=>{e.value=!0}),t),e}();return d((()=>(t.value,Boolean(e()))))}const M=Symbol("vueuse-ssr-width");function O(){const e=v()?t(M,null):null;return"number"==typeof e?e:void 0}function E(t,n={}){const{window:a=b,ssrWidth:r=O()}=n,o=N((()=>a&&"matchMedia"in a&&"function"==typeof a.matchMedia)),l=u("number"==typeof r),s=u(),i=u(!1);return f((()=>{if(l.value){l.value=!o.value;const n=c(t).split(",");i.value=n.some((t=>{const n=t.includes("not all"),a=t.match(/\(\s*min-width:\s*(-?\d+(?:\.\d*)?[a-z]+\s*)\)/),o=t.match(/\(\s*max-width:\s*(-?\d+(?:\.\d*)?[a-z]+\s*)\)/);let l=Boolean(a||o);return a&&l&&(l=r>=e(a[1])),o&&l&&(l=r<=e(o[1])),n?!l:l}))}else o.value&&(s.value=a.matchMedia(c(t)),i.value=s.value.matches)})),S(s,"change",(e=>{i.value=e.matches}),{passive:!0}),d((()=>i.value))}const j="undefined"!=typeof globalThis?globalThis:"undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof self?self:{},A="__vueuse_ssr_handlers__",I=J();function J(){return A in j||(j[A]=j[A]||{}),j[A]}const V={boolean:{read:e=>"true"===e,write:e=>String(e)},object:{read:e=>JSON.parse(e),write:e=>JSON.stringify(e)},number:{read:e=>Number.parseFloat(e),write:e=>String(e)},any:{read:e=>e,write:e=>String(e)},string:{read:e=>e,write:e=>String(e)},map:{read:e=>new Map(JSON.parse(e)),write:e=>JSON.stringify(Array.from(e.entries()))},set:{read:e=>new Set(JSON.parse(e)),write:e=>JSON.stringify(Array.from(e))},date:{read:e=>new Date(e),write:e=>e.toISOString()}},_="vueuse-storage";function D(e,t,n,a={}){var r;const{flush:o="pre",deep:l=!0,listenToStorageChanges:f=!0,writeDefaults:v=!0,mergeDefaults:g=!1,shallow:p,window:w=b,eventFilter:N,onError:M=e=>{},initOnMounted:O}=a,E=(p?u:m)("function"==typeof t?t():t),j=d((()=>c(e)));if(!n)try{n=function(e,t){return I[e]||t}("getDefaultStorage",(()=>{var e;return null==(e=b)?void 0:e.localStorage}))()}catch(F){M(F)}if(!n)return E;const A=c(t),J=function(e){return null==e?"any":e instanceof Set?"set":e instanceof Map?"map":e instanceof Date?"date":"boolean"==typeof e?"boolean":"string"==typeof e?"string":"object"==typeof e?"object":Number.isNaN(e)?"any":"number"}(A),D=null!=(r=a.serializer)?r:V[J],{pause:k,resume:x}=s(E,(()=>function(e){try{const t=n.getItem(j.value);if(null==e)T(t,null),n.removeItem(j.value);else{const a=D.write(e);t!==a&&(n.setItem(j.value,a),T(t,a))}}catch(F){M(F)}}(E.value)),{flush:o,deep:l,eventFilter:N});function T(e,t){if(w){const a={key:j.value,oldValue:e,newValue:t,storageArea:n};w.dispatchEvent(n instanceof Storage?new StorageEvent("storage",a):new CustomEvent(_,{detail:a}))}}function z(e){if(!e||e.storageArea===n)if(e&&null==e.key)E.value=A;else if(!e||e.key===j.value){k();try{(null==e?void 0:e.newValue)!==D.write(E.value)&&(E.value=function(e){const t=e?e.newValue:n.getItem(j.value);if(null==t)return v&&null!=A&&n.setItem(j.value,D.write(A)),A;if(!e&&g){const e=D.read(t);return"function"==typeof g?g(e,A):"object"!==J||Array.isArray(e)?e:{...A,...e}}return"string"!=typeof t?t:D.read(t)}(e))}catch(F){M(F)}finally{e?h(x):x()}}}function B(e){z(e.detail)}return y(j,(()=>z()),{flush:o}),w&&f&&i((()=>{n instanceof Storage?S(w,"storage",z,{passive:!0}):S(w,_,B),O&&z()})),O||z(),E}function k(e,t,n={}){const{window:a=b}=n;return D(e,t,null==a?void 0:a.localStorage,n)}function x(e,t,n={}){const{window:a=b}=n;return D(e,t,null==a?void 0:a.sessionStorage,n)}export{k as a,x as b,E as u};
import{p as e,i as t,b as n,t as a,w as r,c as o,d as l,e as s,f as i}from"./index-CdEJrE2n.js";import{bT as u,av as f,bU as c,k as d,bV as v,o as g,bW as p,bX as w,r as m,x as y,V as h}from"./main-BDlczVyX.js";const b=n?window:void 0;function S(...e){const t=[],n=()=>{t.forEach((e=>e())),t.length=0},s=d((()=>{const t=a(c(e[0])).filter((e=>null!=e));return t.every((e=>"string"!=typeof e))?t:void 0})),i=r((()=>{var t,n;return[null!=(n=null==(t=s.value)?void 0:t.map((e=>function(e){var t;const n=c(e);return null!=(t=null==n?void 0:n.$el)?t:n}(e))))?n:[b].filter((e=>null!=e)),a(c(s.value?e[1]:e[0])),a(w(s.value?e[2]:e[1])),c(s.value?e[3]:e[2])]}),(([e,a,r,o])=>{if(n(),!(null==e?void 0:e.length)||!(null==a?void 0:a.length)||!(null==r?void 0:r.length))return;const s=l(o)?{...o}:o;t.push(...e.flatMap((e=>a.flatMap((t=>r.map((n=>((e,t,n,a)=>(e.addEventListener(t,n,a),()=>e.removeEventListener(t,n,a)))(e,t,n,s))))))))}),{flush:"post"});return o(n),()=>{i(),n()}}function N(e){const t=function(){const e=u(!1),t=p();return t&&g((()=>{e.value=!0}),t),e}();return d((()=>(t.value,Boolean(e()))))}const E=Symbol("vueuse-ssr-width");function M(){const e=v()?t(E,null):null;return"number"==typeof e?e:void 0}function O(t,n={}){const{window:a=b,ssrWidth:r=M()}=n,o=N((()=>a&&"matchMedia"in a&&"function"==typeof a.matchMedia)),l=u("number"==typeof r),s=u(),i=u(!1);return f((()=>{if(l.value){l.value=!o.value;const n=c(t).split(",");i.value=n.some((t=>{const n=t.includes("not all"),a=t.match(/\(\s*min-width:\s*(-?\d+(?:\.\d*)?[a-z]+\s*)\)/),o=t.match(/\(\s*max-width:\s*(-?\d+(?:\.\d*)?[a-z]+\s*)\)/);let l=Boolean(a||o);return a&&l&&(l=r>=e(a[1])),o&&l&&(l=r<=e(o[1])),n?!l:l}))}else o.value&&(s.value=a.matchMedia(c(t)),i.value=s.value.matches)})),S(s,"change",(e=>{i.value=e.matches}),{passive:!0}),d((()=>i.value))}const j="undefined"!=typeof globalThis?globalThis:"undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof self?self:{},A="__vueuse_ssr_handlers__",I=J();function J(){return A in j||(j[A]=j[A]||{}),j[A]}const V={boolean:{read:e=>"true"===e,write:e=>String(e)},object:{read:e=>JSON.parse(e),write:e=>JSON.stringify(e)},number:{read:e=>Number.parseFloat(e),write:e=>String(e)},any:{read:e=>e,write:e=>String(e)},string:{read:e=>e,write:e=>String(e)},map:{read:e=>new Map(JSON.parse(e)),write:e=>JSON.stringify(Array.from(e.entries()))},set:{read:e=>new Set(JSON.parse(e)),write:e=>JSON.stringify(Array.from(e))},date:{read:e=>new Date(e),write:e=>e.toISOString()}},_="vueuse-storage";function D(e,t,n,a={}){var r;const{flush:o="pre",deep:l=!0,listenToStorageChanges:f=!0,writeDefaults:v=!0,mergeDefaults:g=!1,shallow:p,window:w=b,eventFilter:N,onError:E=e=>{},initOnMounted:M}=a,O=(p?u:m)("function"==typeof t?t():t),j=d((()=>c(e)));if(!n)try{n=function(e,t){return I[e]||t}("getDefaultStorage",(()=>{var e;return null==(e=b)?void 0:e.localStorage}))()}catch(B){E(B)}if(!n)return O;const A=c(t),J=function(e){return null==e?"any":e instanceof Set?"set":e instanceof Map?"map":e instanceof Date?"date":"boolean"==typeof e?"boolean":"string"==typeof e?"string":"object"==typeof e?"object":Number.isNaN(e)?"any":"number"}(A),D=null!=(r=a.serializer)?r:V[J],{pause:k,resume:x}=s(O,(()=>function(e){try{const t=n.getItem(j.value);if(null==e)T(t,null),n.removeItem(j.value);else{const a=D.write(e);t!==a&&(n.setItem(j.value,a),T(t,a))}}catch(B){E(B)}}(O.value)),{flush:o,deep:l,eventFilter:N});function T(e,t){if(w){const a={key:j.value,oldValue:e,newValue:t,storageArea:n};w.dispatchEvent(n instanceof Storage?new StorageEvent("storage",a):new CustomEvent(_,{detail:a}))}}function z(e){if(!e||e.storageArea===n)if(e&&null==e.key)O.value=A;else if(!e||e.key===j.value){k();try{(null==e?void 0:e.newValue)!==D.write(O.value)&&(O.value=function(e){const t=e?e.newValue:n.getItem(j.value);if(null==t)return v&&null!=A&&n.setItem(j.value,D.write(A)),A;if(!e&&g){const e=D.read(t);return"function"==typeof g?g(e,A):"object"!==J||Array.isArray(e)?e:{...A,...e}}return"string"!=typeof t?t:D.read(t)}(e))}catch(B){E(B)}finally{e?h(x):x()}}}function F(e){z(e.detail)}return y(j,(()=>z()),{flush:o}),w&&f&&i((()=>{n instanceof Storage?S(w,"storage",z,{passive:!0}):S(w,_,F),M&&z()})),M||z(),O}function k(e,t,n={}){const{window:a=b}=n;return D(e,t,null==a?void 0:a.localStorage,n)}function x(e,t,n={}){const{window:a=b}=n;return D(e,t,null==a?void 0:a.sessionStorage,n)}export{k as a,x as b,O as u};

File diff suppressed because one or more lines are too long

View File

@@ -1 +1 @@
import{bS as e,bX as t,aJ as n,bV as a,bU as i,A as o,x as r,bY as s,aF as u,bT as c,o as l,V as f,J as m,r as p,bZ as v}from"./main-1KUkgCjc.js";function b(e){return!!s()&&(u(e),!0)}const d=new WeakMap,w=(...e)=>{var t;const n=e[0],r=null==(t=a())?void 0:t.proxy;if(null==r&&!i())throw new Error("injectLocal must be called in setup");return r&&d.has(r)&&n in d.get(r)?d.get(r)[n]:o(...e)},g="undefined"!=typeof window&&"undefined"!=typeof document;"undefined"!=typeof WorkerGlobalScope&&(globalThis,WorkerGlobalScope);const h=Object.prototype.toString,y=e=>"[object Object]"===h.call(e),F=()=>{};function j(e,t){return function(...n){return new Promise(((a,i)=>{Promise.resolve(e((()=>t.apply(this,n)),{fn:t,thisArg:this,args:n})).then(a).catch(i)}))}}const A=e=>e();function S(e=A,n={}){const{initialState:a="active"}=n,i=function(...e){if(1!==e.length)return m(...e);const n=e[0];return"function"==typeof n?t(v((()=>({get:n,set:F})))):p(n)}("active"===a);return{isActive:t(i),pause:function(){i.value=!1},resume:function(){i.value=!0},eventFilter:(...t)=>{i.value&&e(...t)}}}function T(e){return e.endsWith("rem")?16*Number.parseFloat(e):Number.parseFloat(e)}function k(e){return Array.isArray(e)?e:[e]}function x(e,t=200,a=!1,i=!0,o=!1){return j(function(...e){let t,a,i,o,r,s,u=0,l=!0,f=F;n(e[0])||"object"!=typeof e[0]?[i,o=!0,r=!0,s=!1]=e:({delay:i,trailing:o=!0,leading:r=!0,rejectOnCancel:s=!1}=e[0]);const m=()=>{t&&(clearTimeout(t),t=void 0,f(),f=F)};return e=>{const n=c(i),p=Date.now()-u,v=()=>a=e();return m(),n<=0?(u=Date.now(),v()):(p>n&&(r||!l)?(u=Date.now(),v()):o&&(a=new Promise(((e,a)=>{f=s?a:e,t=setTimeout((()=>{u=Date.now(),l=!0,e(v()),m()}),Math.max(0,n-p))}))),r||t||(t=setTimeout((()=>l=!0),n)),l=!1,a)}}(t,a,i,o),e)}function D(e,t,n={}){const{eventFilter:a,initialState:i="active",...o}=n,{eventFilter:s,pause:u,resume:c,isActive:l}=S(a,{initialState:i}),f=function(e,t,n={}){const{eventFilter:a=A,...i}=n;return r(e,j(a,t),i)}(e,t,{...o,eventFilter:s});return{stop:f,pause:u,resume:c,isActive:l}}function P(e,t=!0,n){a()?l(e,n):t?e():f(e)}function W(n,a,i={}){const{immediate:o=!0,immediateCallback:r=!1}=i,s=e(!1);let u=null;function l(){u&&(clearTimeout(u),u=null)}function f(){s.value=!1,l()}function m(...e){r&&n(),l(),s.value=!0,u=setTimeout((()=>{s.value=!1,u=null,n(...e)}),c(a))}return o&&(s.value=!0,g&&m()),b(f),{isPending:t(s),start:m,stop:f}}function O(e,t,n){return r(e,t,{...n,immediate:!0})}export{W as a,g as b,b as c,y as d,D as e,P as f,w as i,T as p,k as t,x as u,O as w};
import{bT as e,bY as t,aN as n,bW as a,bV as i,A as o,x as r,bZ as s,aF as u,bU as c,o as l,V as f,J as m,r as p,b_ as v}from"./main-BDlczVyX.js";function b(e){return!!s()&&(u(e),!0)}const d=new WeakMap,w=(...e)=>{var t;const n=e[0],r=null==(t=a())?void 0:t.proxy;if(null==r&&!i())throw new Error("injectLocal must be called in setup");return r&&d.has(r)&&n in d.get(r)?d.get(r)[n]:o(...e)},g="undefined"!=typeof window&&"undefined"!=typeof document;"undefined"!=typeof WorkerGlobalScope&&(globalThis,WorkerGlobalScope);const h=Object.prototype.toString,y=e=>"[object Object]"===h.call(e),F=()=>{};function j(e,t){return function(...n){return new Promise(((a,i)=>{Promise.resolve(e((()=>t.apply(this,n)),{fn:t,thisArg:this,args:n})).then(a).catch(i)}))}}const A=e=>e();function T(e=A,n={}){const{initialState:a="active"}=n,i=function(...e){if(1!==e.length)return m(...e);const n=e[0];return"function"==typeof n?t(v((()=>({get:n,set:F})))):p(n)}("active"===a);return{isActive:t(i),pause:function(){i.value=!1},resume:function(){i.value=!0},eventFilter:(...t)=>{i.value&&e(...t)}}}function S(e){return e.endsWith("rem")?16*Number.parseFloat(e):Number.parseFloat(e)}function W(e){return Array.isArray(e)?e:[e]}function k(e,t=200,a=!1,i=!0,o=!1){return j(function(...e){let t,a,i,o,r,s,u=0,l=!0,f=F;n(e[0])||"object"!=typeof e[0]?[i,o=!0,r=!0,s=!1]=e:({delay:i,trailing:o=!0,leading:r=!0,rejectOnCancel:s=!1}=e[0]);const m=()=>{t&&(clearTimeout(t),t=void 0,f(),f=F)};return e=>{const n=c(i),p=Date.now()-u,v=()=>a=e();return m(),n<=0?(u=Date.now(),v()):(p>n&&(r||!l)?(u=Date.now(),v()):o&&(a=new Promise(((e,a)=>{f=s?a:e,t=setTimeout((()=>{u=Date.now(),l=!0,e(v()),m()}),Math.max(0,n-p))}))),r||t||(t=setTimeout((()=>l=!0),n)),l=!1,a)}}(t,a,i,o),e)}function x(e,t,n={}){const{eventFilter:a,initialState:i="active",...o}=n,{eventFilter:s,pause:u,resume:c,isActive:l}=T(a,{initialState:i}),f=function(e,t,n={}){const{eventFilter:a=A,...i}=n;return r(e,j(a,t),i)}(e,t,{...o,eventFilter:s});return{stop:f,pause:u,resume:c,isActive:l}}function D(e,t=!0,n){a()?l(e,n):t?e():f(e)}function P(n,a,i={}){const{immediate:o=!0,immediateCallback:r=!1}=i,s=e(!1);let u=null;function l(){u&&(clearTimeout(u),u=null)}function f(){s.value=!1,l()}function m(...e){r&&n(),l(),s.value=!0,u=setTimeout((()=>{s.value=!1,u=null,n(...e)}),c(a))}return o&&(s.value=!0,g&&m()),b(f),{isPending:t(s),start:m,stop:f}}function N(e,t,n){return r(e,t,{...n,immediate:!0})}export{P as a,g as b,b as c,y as d,x as e,D as f,w as i,S as p,W as t,k as u,N as w};

File diff suppressed because one or more lines are too long

View File

@@ -1 +0,0 @@
import{S as e}from"./index-CqYMVimh.js";import{r as t,k as l,x as a,d as u,c as i,w as n,t as o,$ as s,m as r,aW as d,bB as p,B as v,i as f}from"./main-1KUkgCjc.js";import{u as c}from"./useStore-CgJ3uN_c.js";import{M as y}from"./data-Cu_-2gKL.js";import{N as m,a as b}from"./business-CulOz_oE.js";function h(e){return"function"==typeof e||"[object Object]"===Object.prototype.toString.call(e)&&!f(e)}const g=u({name:"NotifyProviderSelect",props:{path:{type:String,default:""},value:{type:String,default:""},valueType:{type:String,default:"value",validator:e=>["value","type"].includes(e)},isAddMode:{type:Boolean,default:!1}},emits:{"update:value":e=>"object"==typeof e&&null!==e&&"label"in e&&"value"in e&&"type"in e},setup(u,{emit:f}){const{selectOptions:g,goToAddNotifyProvider:_,handleSelectUpdate:j,fetchNotifyProviderData:x}=function(e,u){const{fetchNotifyProvider:i,notifyProvider:n}=c(),o=t({label:"",value:"",type:""}),s=t([]),r=l((()=>Object.entries(y).map((([t,l])=>({label:l.name,value:"value"===e.valueType?t:l.type,type:l.type}))))),d=e=>{if(!e)return void(o.value={label:"",value:"",type:""});const t=s.value.find((t=>t.value===e));if(t)return void(o.value={...t});const l=r.value.find((t=>t.value===e));o.value=l?{...l}:{label:e,value:e,type:""}},p=()=>{i()};return a((()=>e.value),(e=>{0===s.value.length&&e&&p(),d(e)}),{immediate:!0}),a((()=>n.value),(t=>{t&&t.length>0?s.value=t.map((t=>({label:t.label,value:"value"===e.valueType?t.value:t.type,type:t.type}))):s.value=r.value,d(e.value)}),{immediate:!0,deep:!0}),n.value&&0!==n.value.length||(s.value=r.value,p()),{selectedOptionFull:o,selectOptions:s,goToAddNotifyProvider:()=>{window.open("/settings?tab=notification","_blank")},handleSelectUpdate:e=>{d(e),u("update:value",{...o.value})},fetchNotifyProviderData:p}}(u,f),S=({option:t})=>{let l;const a=t;return i("div",{class:"flex items-center"},[a.label?i(b,{align:"center",size:"small"},{default:()=>[i(e,{icon:`notify-${a.type||""}`,size:"1.6rem"},null),i(m,null,{default:()=>[a.label]})]}):i(m,{depth:"3"},h(l=s("t_0_1745887835267"))?l:{default:()=>[l]})])},N=t=>{const l=t;return i(b,{align:"center",size:"small"},{default:()=>[i(e,{icon:`notify-${l.type||""}`,size:"1.6rem"},null),i(m,null,{default:()=>[l.label]})]})},P=l((()=>g.value.map((e=>({...e})))));return()=>{let e,t;return i(n,{cols:24},{default:()=>[i(o,{span:u.isAddMode?13:24,label:s("t_1_1745887832941"),path:u.path},{default:()=>[i(r,{class:"flex-1 w-full",options:P.value,renderLabel:N,renderTag:S,filterable:!0,clearable:!0,placeholder:s("t_0_1745887835267"),value:u.value,onUpdateValue:j},{empty:()=>i("div",{class:"text-center py-4"},[i(m,{depth:"3",class:"text-[1.4rem]"},{default:()=>[0===g.value.length?s("t_0_1745887835267"):"暂无匹配的通知渠道"]})])})]}),u.isAddMode&&i(d,{span:11},{default:()=>[i("div",{class:"flex items-center h-full"},[i(p,{vertical:!0},null),i(v,{class:"mx-[8px]",onClick:_,ghost:!0},h(e=s("t_2_1745887834248"))?e:{default:()=>[e]}),i(v,{onClick:x,ghost:!0},h(t=s("t_0_1746497662220"))?t:{default:()=>[t]})])]})]})}}});export{g as N};

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@@ -1 +1 @@
import{d as e,Y as a,Z as l,_ as t,aJ as s,r,k as n,x as i,aK as o,aL as c,c as u,a3 as d,q as m,aa as p,$ as h,b as v,B as x}from"./main-1KUkgCjc.js";const f={xmlns:"http://www.w3.org/2000/svg","xmlns:xlink":"http://www.w3.org/1999/xlink",viewBox:"0 0 512 512"},y=e({name:"Search",render:function(e,s){return l(),a("svg",f,s[0]||(s[0]=[t("path",{d:"M456.69 421.39L362.6 327.3a173.81 173.81 0 0 0 34.84-104.58C397.44 126.38 319.06 48 222.72 48S48 126.38 48 222.72s78.38 174.72 174.72 174.72A173.81 173.81 0 0 0 327.3 362.6l94.09 94.09a25 25 0 0 0 35.3-35.3zM97.92 222.72a124.8 124.8 0 1 1 124.8 124.8a124.95 124.95 0 0 1-124.8-124.8z",fill:"currentColor"},null,-1)]))}});function b(e={}){const{onSearch:a,value:l="",placeholder:t="请输入搜索内容",clearDelay:p=100,size:h="large",clearable:v=!0,className:x="min-w-[300px]",disabled:f=!1,trim:b=!0,immediate:g=!1,debounceDelay:w=300}=e,k=s(l)?l:r(l),_=n((()=>(b?k.value.trim():k.value).length>0)),C=(e=!1)=>{if(a){const l=b?k.value.trim():k.value;a(l,e)}},S=o((()=>{C()}),w);g&&a&&i(k,(()=>{S()}));const z=e=>{"Enter"===e.key&&C()},B=()=>{k.value="",c((()=>{C(!0)}),p)},q=()=>{C(!0)};return{value:k,hasSearchValue:_,handleKeydown:z,handleClear:B,handleSearchClick:q,search:C,debouncedSearch:S,clear:()=>{k.value=""},setValue:e=>{k.value=e},SearchComponent:(e={})=>{const a={value:k.value,"onUpdate:value":e=>{k.value=e},onKeydown:z,onClear:B,placeholder:t,clearable:v,size:h,disabled:f,class:x,...e};return u(m,a,{suffix:()=>u("div",{class:"flex items-center cursor-pointer",onClick:q},[u(d,{component:y,class:"text-[var(--text-color-3)] w-[1.6rem] font-bold"},null)])})}}}const g=e({name:"TableEmptyState",props:{addButtonText:{type:String,required:!0},onAddClick:{type:Function,required:!0}},setup:e=>()=>u("div",{class:"flex justify-center items-center h-full"},[u(p,{class:"px-[4rem]"},{default:()=>[h("t_1_1747754231838"),u(x,{text:!0,type:"primary",size:"small",onClick:e.onAddClick},{default:()=>[e.addButtonText]}),v(""),h("t_2_1747754234999"),u(x,{text:!0,tag:"a",target:"_blank",type:"primary",href:"https://github.com/allinssl/allinssl/issues"},{default:()=>[v("Issues")]}),v(""),h("t_3_1747754232000"),u(x,{text:!0,tag:"a",target:"_blank",type:"primary",href:"https://github.com/allinssl/allinssl"},{default:()=>[v("Star")]}),v(""),h("t_4_1747754235407")]})])});export{g as E,b as u};
import{d as e,Y as a,Z as l,_ as t,aN as s,r,k as n,x as i,aO as o,aP as c,c as u,a3 as d,q as m,aa as p,$ as h,b as v,B as x}from"./main-BDlczVyX.js";const f={xmlns:"http://www.w3.org/2000/svg","xmlns:xlink":"http://www.w3.org/1999/xlink",viewBox:"0 0 512 512"},y=e({name:"Search",render:function(e,s){return l(),a("svg",f,s[0]||(s[0]=[t("path",{d:"M456.69 421.39L362.6 327.3a173.81 173.81 0 0 0 34.84-104.58C397.44 126.38 319.06 48 222.72 48S48 126.38 48 222.72s78.38 174.72 174.72 174.72A173.81 173.81 0 0 0 327.3 362.6l94.09 94.09a25 25 0 0 0 35.3-35.3zM97.92 222.72a124.8 124.8 0 1 1 124.8 124.8a124.95 124.95 0 0 1-124.8-124.8z",fill:"currentColor"},null,-1)]))}});function b(e={}){const{onSearch:a,value:l="",placeholder:t="请输入搜索内容",clearDelay:p=100,size:h="large",clearable:v=!0,className:x="min-w-[300px]",disabled:f=!1,trim:b=!0,immediate:g=!1,debounceDelay:w=300}=e,k=s(l)?l:r(l),_=n((()=>(b?k.value.trim():k.value).length>0)),C=(e=!1)=>{if(a){const l=b?k.value.trim():k.value;a(l,e)}},S=o((()=>{C()}),w);g&&a&&i(k,(()=>{S()}));const z=e=>{"Enter"===e.key&&C()},B=()=>{k.value="",c((()=>{C(!0)}),p)},q=()=>{C(!0)};return{value:k,hasSearchValue:_,handleKeydown:z,handleClear:B,handleSearchClick:q,search:C,debouncedSearch:S,clear:()=>{k.value=""},setValue:e=>{k.value=e},SearchComponent:(e={})=>{const a={value:k.value,"onUpdate:value":e=>{k.value=e},onKeydown:z,onClear:B,placeholder:t,clearable:v,size:h,disabled:f,class:x,...e};return u(m,a,{suffix:()=>u("div",{class:"flex items-center cursor-pointer",onClick:q},[u(d,{component:y,class:"text-[var(--text-color-3)] w-[1.6rem] font-bold"},null)])})}}}const g=e({name:"TableEmptyState",props:{addButtonText:{type:String,required:!0},onAddClick:{type:Function,required:!0}},setup:e=>()=>u("div",{class:"flex justify-center items-center h-full"},[u(p,{class:"px-[4rem]"},{default:()=>[h("t_1_1747754231838"),u(x,{text:!0,type:"primary",size:"small",onClick:e.onAddClick},{default:()=>[e.addButtonText]}),v(""),h("t_2_1747754234999"),u(x,{text:!0,tag:"a",target:"_blank",type:"primary",href:"https://github.com/allinssl/allinssl/issues"},{default:()=>[v("Issues")]}),v(""),h("t_3_1747754232000"),u(x,{text:!0,tag:"a",target:"_blank",type:"primary",href:"https://github.com/allinssl/allinssl"},{default:()=>[v("Star")]}),v(""),h("t_4_1747754235407")]})])});export{g as E,b as u};

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@@ -1 +0,0 @@
import{u as e}from"./useStore-CgJ3uN_c.js";import{u as a,N as l}from"./index-C7mXt0yr.js";import{r as t,x as u,o as v,aD as s,$ as d,d as r,c as o,w as n,t as i,m as p,B as y,i as c}from"./main-1KUkgCjc.js";import{S as f}from"./index-CqYMVimh.js";import{N as m,a as b}from"./business-CulOz_oE.js";const _=r({name:"DnsProviderSelect",props:{type:{type:String,required:!0},path:{type:String,required:!0},value:{type:String,required:!0},valueType:{type:String,default:"value"},isAddMode:{type:Boolean,default:!0},disabled:{type:Boolean,default:!1},customClass:{type:String,default:""}},emits:["update:value"],setup(r,{emit:_}){const g=function(l,r){const{handleError:o}=a(),{fetchDnsProvider:n,resetDnsProvider:i,dnsProvider:p}=e(),y=t({label:"",value:"",type:"",data:{}}),c=t([]),f=t(!1),m=t(""),b=()=>{var e,a,t,u,v;const s=p.value.find((e=>("value"===l.valueType?e.value:e.type)===y.value.value));s?(y.value={label:s.label,value:"value"===l.valueType?s.value:s.type,type:"value"===l.valueType?s.type:s.value,data:s},r("update:value",{...y.value})):""===y.value.value&&p.value.length>0&&(y.value={label:(null==(e=p.value[0])?void 0:e.label)||"",value:"value"===l.valueType?(null==(a=p.value[0])?void 0:a.value)||"":(null==(t=p.value[0])?void 0:t.type)||"",type:"value"===l.valueType?(null==(u=p.value[0])?void 0:u.type)||"":(null==(v=p.value[0])?void 0:v.value)||"",data:p.value[0]||{}},r("update:value",{...y.value}))},_=e=>{y.value.value=e,b()},g=async(e=l.type)=>{f.value=!0,m.value="";try{await n(e),l.value?(y.value.value=l.value,b()):b()}catch(a){m.value="string"==typeof a?a:d("t_0_1746760933542"),o(a)}finally{f.value=!1}};return u((()=>p.value),(e=>{var a;c.value=e.map((e=>({label:e.label,value:"value"===l.valueType?e.value:e.type,type:"value"===l.valueType?e.type:e.value,data:e})))||[],c.value.some((e=>e.value===y.value.value))?b():l.value&&c.value.some((e=>e.value===l.value))?(y.value.value=l.value,b()):""===y.value.value&&c.value.length>0&&(y.value.value=(null==(a=c.value[0])?void 0:a.value)||"",b())}),{deep:!0}),u((()=>l.value),(e=>{e!==y.value.value&&_(e)}),{immediate:!0}),u((()=>l.type),(e=>{g(e)})),v((async()=>{await g(l.type)})),s((()=>{i()})),{param:y,dnsProviderRef:c,isLoading:f,errorMessage:m,goToAddDnsProvider:()=>{window.open("/auth-api-manage","_blank")},handleUpdateValue:_,loadDnsProviders:g,handleFilter:(e,a)=>a.label.toLowerCase().includes(e.toLowerCase())}}(r,_),h=e=>o(b,{align:"center"},{default:()=>[o(f,{icon:`resources-${e.type}`,size:"2rem"},null),o(m,null,{default:()=>[e.label]})]});return()=>{let e;return o(l,{show:g.isLoading.value},{default:()=>[o(n,{cols:24,class:r.customClass},{default:()=>[o(i,{span:r.isAddMode?13:24,label:"dns"===r.type?d("t_3_1745735765112"):d("t_0_1746754500246"),path:r.path},{default:()=>[o(p,{class:"flex-1 w-full",filterable:!0,options:g.dnsProviderRef.value,renderLabel:h,renderTag:({option:e})=>(({option:e})=>o(b,{align:"center"},{default:()=>[e.label?h(e):o(m,{class:"text-[#aaa]"},{default:()=>["dns"===r.type?d("t_0_1747019621052"):d("t_0_1746858920894")]})]}))({option:e}),filter:(e,a)=>g.handleFilter(e,a),placeholder:"dns"===r.type?d("t_3_1745490735059"):d("t_0_1746858920894"),value:g.param.value.value,onUpdateValue:g.handleUpdateValue,disabled:r.disabled},{empty:()=>o("span",{class:"text-[1.4rem]"},[g.errorMessage.value||("dns"===r.type?d("t_1_1746858922914"):d("t_2_1746858923964"))])})]}),r.isAddMode&&o(i,{span:11},{default:()=>{return[o(y,{class:"mx-[8px]",onClick:g.goToAddDnsProvider,disabled:r.disabled},{default:()=>["dns"===r.type?d("t_1_1746004861166"):d("t_3_1746858920060")]}),o(y,{onClick:()=>g.loadDnsProviders(r.type),loading:g.isLoading.value,disabled:r.disabled},(a=e=d("t_0_1746497662220"),"function"==typeof a||"[object Object]"===Object.prototype.toString.call(a)&&!c(a)?e:{default:()=>[e]}))];var a}})]})]})}}});export{_ as D};

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1 @@
import{c as o}from"./index-5v0IClw2.js";const t=t=>o("/v1/monitor/get_list",t),r=t=>o("/v1/monitor/add_monitor",t),i=t=>o("/v1/monitor/upd_monitor",t),n=t=>o("/v1/monitor/del_monitor",t),m=t=>o("/v1/monitor/set_monitor",t),s=t=>o("/v1/monitor/get_monitor_info",t),a=t=>o("/v1/monitor/get_err_record",t);export{r as a,s as b,a as c,n as d,t as g,m as s,i as u};

View File

@@ -1 +1 @@
import{c as s,d as o}from"./index-C7mXt0yr.js";const e=o=>s("/v1/login/sign",o),g=()=>o.get("/v1/login/get_code"),i=()=>s("/v1/login/sign-out",{}),v=o=>s("/v1/overview/get_overviews",o);export{g as a,v as g,e as l,i as s};
import{c as s,d as o}from"./index-5v0IClw2.js";const e=o=>s("/v1/login/sign",o),g=()=>o.get("/v1/login/get_code"),i=()=>s("/v1/login/sign-out",{}),v=o=>s("/v1/overview/get_overviews",o);export{g as a,v as g,e as l,i as s};

View File

@@ -1 +1 @@
import{c as t}from"./index-C7mXt0yr.js";const e=e=>t("/v1/setting/get_setting",e),s=e=>t("/v1/setting/save_setting",e),r=e=>t("/v1/report/add_report",e),o=e=>t("/v1/report/upd_report",e),a=e=>t("/v1/report/del_report",e),p=e=>t("/v1/report/notify_test",e),i=e=>t("/v1/report/get_list",e),v=e=>t("/v1/setting/get_version",e);export{e as a,i as b,r as c,a as d,v as g,s,p as t,o as u};
import{c as t}from"./index-5v0IClw2.js";const e=e=>t("/v1/setting/get_setting",e),s=e=>t("/v1/setting/save_setting",e),r=e=>t("/v1/report/add_report",e),o=e=>t("/v1/report/upd_report",e),a=e=>t("/v1/report/del_report",e),p=e=>t("/v1/report/notify_test",e),i=e=>t("/v1/report/get_list",e),v=e=>t("/v1/setting/get_version",e);export{e as a,i as b,r as c,a as d,v as g,s,p as t,o as u};

View File

@@ -0,0 +1 @@
import{E as e,F as o,d as t,H as n,I as r,K as s,cc as i,k as l,aW as a,M as d,aw as c}from"./main-BDlczVyX.js";const h=e("text","\n transition: color .3s var(--n-bezier);\n color: var(--n-text-color);\n",[o("strong","\n font-weight: var(--n-font-weight-strong);\n "),o("italic",{fontStyle:"italic"}),o("underline",{textDecoration:"underline"}),o("code","\n line-height: 1.4;\n display: inline-block;\n font-family: var(--n-font-famliy-mono);\n transition: \n color .3s var(--n-bezier),\n border-color .3s var(--n-bezier),\n background-color .3s var(--n-bezier);\n box-sizing: border-box;\n padding: .05em .35em 0 .35em;\n border-radius: var(--n-code-border-radius);\n font-size: .9em;\n color: var(--n-code-text-color);\n background-color: var(--n-code-color);\n border: var(--n-code-border);\n ")]),g=t({name:"Text",props:Object.assign(Object.assign({},s.props),{code:Boolean,type:{type:String,default:"default"},delete:Boolean,strong:Boolean,italic:Boolean,underline:Boolean,depth:[String,Number],tag:String,as:{type:String,validator:()=>!0,default:void 0}}),setup(e){const{mergedClsPrefixRef:o,inlineThemeDisabled:t}=r(e),n=s("Typography","-text",h,i,e,o),g=l((()=>{const{depth:o,type:t}=e,r="default"===t?void 0===o?"textColor":`textColor${o}Depth`:a("textColor",t),{common:{fontWeightStrong:s,fontFamilyMono:i,cubicBezierEaseInOut:l},self:{codeTextColor:d,codeBorderRadius:c,codeColor:h,codeBorder:g,[r]:u}}=n.value;return{"--n-bezier":l,"--n-text-color":u,"--n-font-weight-strong":s,"--n-font-famliy-mono":i,"--n-code-border-radius":c,"--n-code-text-color":d,"--n-code-color":h,"--n-code-border":g}})),u=t?d("text",l((()=>`${e.type[0]}${e.depth||""}`)),g,e):void 0;return{mergedClsPrefix:o,compitableTag:c(e,["as","tag"]),cssVars:t?void 0:g,themeClass:null==u?void 0:u.themeClass,onRender:null==u?void 0:u.onRender}},render(){var e,o,t;const{mergedClsPrefix:r}=this;null===(e=this.onRender)||void 0===e||e.call(this);const s=[`${r}-text`,this.themeClass,{[`${r}-text--code`]:this.code,[`${r}-text--delete`]:this.delete,[`${r}-text--strong`]:this.strong,[`${r}-text--italic`]:this.italic,[`${r}-text--underline`]:this.underline}],i=null===(t=(o=this.$slots).default)||void 0===t?void 0:t.call(o);return this.code?n("code",{class:s,style:this.cssVars},this.delete?n("del",null,i):i):this.delete?n("del",{class:s,style:this.cssVars},i):n(this.compitableTag||"span",{class:s,style:this.cssVars},i)}});export{g as N};

View File

@@ -1 +1 @@
import{c8 as t,c9 as n,ca as i}from"./main-1KUkgCjc.js";var r=/\s/;var e=/^\s+/;function a(t){return t?t.slice(0,function(t){for(var n=t.length;n--&&r.test(t.charAt(n)););return n}(t)+1).replace(e,""):t}var o=/^[-+]0x[0-9a-f]+$/i,u=/^0b[01]+$/i,f=/^0o[0-7]+$/i,c=parseInt;function v(i){if("number"==typeof i)return i;if(t(i))return NaN;if(n(i)){var r="function"==typeof i.valueOf?i.valueOf():i;i=n(r)?r+"":r}if("string"!=typeof i)return 0===i?i:+i;i=a(i);var e=u.test(i);return e||f.test(i)?c(i.slice(2),e?2:8):o.test(i)?NaN:+i}var s=function(){return i.Date.now()},l=Math.max,d=Math.min;function m(t,i,r){var e,a,o,u,f,c,m=0,p=!1,g=!1,h=!0;if("function"!=typeof t)throw new TypeError("Expected a function");function x(n){var i=e,r=a;return e=a=void 0,m=n,u=t.apply(r,i)}function y(t){var n=t-c;return void 0===c||n>=i||n<0||g&&t-m>=o}function T(){var t=s();if(y(t))return w(t);f=setTimeout(T,function(t){var n=i-(t-c);return g?d(n,o-(t-m)):n}(t))}function w(t){return f=void 0,h&&e?x(t):(e=a=void 0,u)}function E(){var t=s(),n=y(t);if(e=arguments,a=this,c=t,n){if(void 0===f)return function(t){return m=t,f=setTimeout(T,i),p?x(t):u}(c);if(g)return clearTimeout(f),f=setTimeout(T,i),x(c)}return void 0===f&&(f=setTimeout(T,i)),u}return i=v(i)||0,n(r)&&(p=!!r.leading,o=(g="maxWait"in r)?l(v(r.maxWait)||0,i):o,h="trailing"in r?!!r.trailing:h),E.cancel=function(){void 0!==f&&clearTimeout(f),m=0,e=c=a=f=void 0},E.flush=function(){return void 0===f?u:w(s())},E}function p(t,i,r){var e=!0,a=!0;if("function"!=typeof t)throw new TypeError("Expected a function");return n(r)&&(e="leading"in r?!!r.leading:e,a="trailing"in r?!!r.trailing:a),m(t,i,{leading:e,maxWait:i,trailing:a})}export{p as t};
import{c9 as t,ca as n,cb as i}from"./main-BDlczVyX.js";var r=/\s/;var e=/^\s+/;function a(t){return t?t.slice(0,function(t){for(var n=t.length;n--&&r.test(t.charAt(n)););return n}(t)+1).replace(e,""):t}var o=/^[-+]0x[0-9a-f]+$/i,u=/^0b[01]+$/i,f=/^0o[0-7]+$/i,c=parseInt;function v(i){if("number"==typeof i)return i;if(t(i))return NaN;if(n(i)){var r="function"==typeof i.valueOf?i.valueOf():i;i=n(r)?r+"":r}if("string"!=typeof i)return 0===i?i:+i;i=a(i);var e=u.test(i);return e||f.test(i)?c(i.slice(2),e?2:8):o.test(i)?NaN:+i}var s=function(){return i.Date.now()},l=Math.max,d=Math.min;function m(t,i,r){var e,a,o,u,f,c,m=0,p=!1,g=!1,h=!0;if("function"!=typeof t)throw new TypeError("Expected a function");function x(n){var i=e,r=a;return e=a=void 0,m=n,u=t.apply(r,i)}function y(t){var n=t-c;return void 0===c||n>=i||n<0||g&&t-m>=o}function T(){var t=s();if(y(t))return w(t);f=setTimeout(T,function(t){var n=i-(t-c);return g?d(n,o-(t-m)):n}(t))}function w(t){return f=void 0,h&&e?x(t):(e=a=void 0,u)}function E(){var t=s(),n=y(t);if(e=arguments,a=this,c=t,n){if(void 0===f)return function(t){return m=t,f=setTimeout(T,i),p?x(t):u}(c);if(g)return clearTimeout(f),f=setTimeout(T,i),x(c)}return void 0===f&&(f=setTimeout(T,i)),u}return i=v(i)||0,n(r)&&(p=!!r.leading,o=(g="maxWait"in r)?l(v(r.maxWait)||0,i):o,h="trailing"in r?!!r.trailing:h),E.cancel=function(){void 0!==f&&clearTimeout(f),m=0,e=c=a=f=void 0},E.flush=function(){return void 0===f?u:w(s())},E}function p(t,i,r){var e=!0,a=!0;if("function"!=typeof t)throw new TypeError("Expected a function");return n(r)&&(e="leading"in r?!!r.leading:e,a="trailing"in r?!!r.trailing:a),m(t,i,{leading:e,maxWait:i,trailing:a})}export{p as t};

View File

@@ -1 +1 @@
import{e,s as a,r as t,k as o,$ as l}from"./main-1KUkgCjc.js";import{a as s,b as n}from"./index-BLPUn6mO.js";import{u as r}from"./index-C7mXt0yr.js";import{b as i}from"./setting-Cy4-AOZ6.js";import{j as u}from"./access-Xajiehoa.js";const m=e("layout-store",(()=>{const{handleError:e}=r(),a=s("layout-collapsed",!1),m=t([]),c=t([]),v=n("menu-active","home"),d=o((()=>"home"!==v.value?"var(--n-content-padding)":"0")),p=s("locales-active","zhCN"),h=t({mail:{name:l("t_68_1745289354676")},dingtalk:{name:l("t_32_1746773348993")},wecom:{name:l("t_33_1746773350932")},feishu:{name:l("t_34_1746773350153")},webhook:{name:"WebHook"}});return{isCollapsed:a,notifyProvider:m,dnsProvider:c,menuActive:v,layoutPadding:d,locales:p,pushSourceType:h,toggleCollapse:()=>{a.value=!a.value},handleCollapse:()=>{a.value=!0},handleExpand:()=>{a.value=!1},updateMenuActive:e=>{"logout"!==e&&(v.value=e)},resetDataInfo:()=>{v.value="home",sessionStorage.removeItem("menu-active")},fetchNotifyProvider:async()=>{try{m.value=[];const{data:e}=await i({p:1,search:"",limit:1e3}).fetch();m.value=(null==e?void 0:e.map((e=>({label:e.name,value:e.id.toString(),type:e.type}))))||[]}catch(a){e(a)}},fetchDnsProvider:async(a="")=>{try{c.value=[];const{data:e}=await u({type:a}).fetch();c.value=(null==e?void 0:e.map((e=>({label:e.name,value:e.id.toString(),type:e.type,data:e}))))||[]}catch(t){c.value=[],e(t)}},resetDnsProvider:()=>{c.value=[]}}})),c=()=>{const e=m();return{...e,...a(e)}};export{c as u};
import{e,s as a,r as t,k as o,$ as s}from"./main-BDlczVyX.js";import{a as l,b as n}from"./index-CRwde6SK.js";import{u as r}from"./index-5v0IClw2.js";import{b as i}from"./setting-4THWX3Fi.js";import{j as u}from"./access-D-zvf6ZM.js";const m=e("layout-store",(()=>{const{handleError:e}=r(),a=l("layout-collapsed",!1),m=t([]),c=t([]),v=n("menu-active","home"),d=o((()=>"home"!==v.value?"var(--n-content-padding)":"0")),p=l("locales-active","zhCN"),h=t({mail:{name:s("t_68_1745289354676")},dingtalk:{name:s("t_32_1746773348993")},wecom:{name:s("t_33_1746773350932")},feishu:{name:s("t_34_1746773350153")},webhook:{name:"WebHook"}});return{isCollapsed:a,notifyProvider:m,dnsProvider:c,menuActive:v,layoutPadding:d,locales:p,pushSourceType:h,toggleCollapse:()=>{a.value=!a.value},handleCollapse:()=>{a.value=!0},handleExpand:()=>{a.value=!1},updateMenuActive:e=>{"logout"!==e&&(v.value=e)},resetDataInfo:()=>{v.value="home",sessionStorage.removeItem("menu-active")},fetchNotifyProvider:async()=>{try{m.value=[];const{data:e}=await i({p:1,search:"",limit:1e3}).fetch();m.value=(null==e?void 0:e.map((e=>({label:e.name,value:e.id.toString(),type:e.type}))))||[]}catch(a){e(a)}},fetchDnsProvider:async(a="")=>{try{c.value=[];const{data:e}=await u({type:a}).fetch();c.value=(null==e?void 0:e.map((e=>({label:e.name,value:e.id.toString(),type:e.type,data:e}))))||[]}catch(t){c.value=[],e(t)}},resetDnsProvider:()=>{c.value=[]}}})),c=()=>{const e=m();return{...e,...a(e)}};export{c as u};

View File

@@ -1 +1 @@
import{c as e,u as a}from"./index-C7mXt0yr.js";import{e as o,s as t,r as l,$ as r}from"./main-1KUkgCjc.js";const w=a=>e("/v1/workflow/get_list",a),s=a=>e("/v1/workflow/del_workflow",a),c=a=>e("/v1/workflow/get_workflow_history",a),f=a=>e("/v1/workflow/get_exec_log",a),n=a=>e("/v1/workflow/execute_workflow",a),d=a=>e("/v1/workflow/exec_type",a),i=a=>e("/v1/workflow/active",a),k=a=>e("/v1/workflow/stop",a),u=o("work-edit-view-store",(()=>{const{handleError:o}=a(),t=l(!1),w=l(!1),s=l({id:"",name:"",content:"",active:"1",exec_type:"manual"}),c=l("quick"),f=l({id:"",name:"",childNode:{id:"start-1",name:"开始",type:"start",config:{exec_type:"manual"},childNode:null}});return{isEdit:t,detectionRefresh:w,workflowData:s,workflowType:c,workDefalutNodeData:f,resetWorkflowData:()=>{s.value={id:"",name:"",content:"",active:"1",exec_type:"manual"},f.value={id:"",name:"",childNode:{id:"start-1",name:"开始",type:"start",config:{exec_type:"manual"},childNode:null}},c.value="quick",t.value=!1},addNewWorkflow:async a=>{try{const{message:o,fetch:t}=(a=>e("/v1/workflow/add_workflow",a))(a);o.value=!0,await t()}catch(t){o(t).default(r("t_10_1745457486451"))}},updateWorkflowData:async a=>{try{const{message:o,fetch:t}=e("/v1/workflow/upd_workflow",a);o.value=!0,await t()}catch(t){o(t).default(r("t_11_1745457488256"))}}}})),v=()=>{const e=u();return{...e,...t(e)}};export{c as a,n as b,f as c,s as d,i as e,v as f,w as g,k as s,d as u};
import{c as e,u as a}from"./index-5v0IClw2.js";import{e as o,s as t,r as l,$ as r}from"./main-BDlczVyX.js";const w=a=>e("/v1/workflow/get_list",a),s=a=>e("/v1/workflow/del_workflow",a),c=a=>e("/v1/workflow/get_workflow_history",a),f=a=>e("/v1/workflow/get_exec_log",a),n=a=>e("/v1/workflow/execute_workflow",a),d=a=>e("/v1/workflow/exec_type",a),i=a=>e("/v1/workflow/active",a),k=a=>e("/v1/workflow/stop",a),u=o("work-edit-view-store",(()=>{const{handleError:o}=a(),t=l(!1),w=l(!1),s=l({id:"",name:"",content:"",active:"1",exec_type:"manual"}),c=l("quick"),f=l({id:"",name:"",childNode:{id:"start-1",name:"开始",type:"start",config:{exec_type:"manual"},childNode:null}});return{isEdit:t,detectionRefresh:w,workflowData:s,workflowType:c,workDefalutNodeData:f,resetWorkflowData:()=>{s.value={id:"",name:"",content:"",active:"1",exec_type:"manual"},f.value={id:"",name:"",childNode:{id:"start-1",name:"开始",type:"start",config:{exec_type:"manual"},childNode:null}},c.value="quick",t.value=!1},addNewWorkflow:async a=>{try{const{message:o,fetch:t}=(a=>e("/v1/workflow/add_workflow",a))(a);o.value=!0,await t()}catch(t){o(t).default(r("t_10_1745457486451"))}},updateWorkflowData:async a=>{try{const{message:o,fetch:t}=e("/v1/workflow/upd_workflow",a);o.value=!0,await t()}catch(t){o(t).default(r("t_11_1745457488256"))}}}})),v=()=>{const e=u();return{...e,...t(e)}};export{c as a,n as b,f as c,s as d,i as e,v as f,w as g,k as s,d as u};