mirror of
https://gitee.com/mirrors/AllinSSL.git
synced 2026-03-11 17:20:10 +08:00
【新增】在翻译文件中添加多吉云AccessKey和SecretKey的相关翻译,更新阿里云ESA的配置接口,优化CA管理功能,增强表单验证逻辑,提升用户体验。
This commit is contained in:
@@ -15,7 +15,7 @@ import BaseComponent from '@components/BaseLayout'
|
||||
export default defineComponent({
|
||||
name: 'AuthApiManage',
|
||||
setup() {
|
||||
const { TableComponent, PageComponent, param, fetch, total, openAddForm } = useController()
|
||||
const { TableComponent, PageComponent, SearchComponent, openAddForm } = useController()
|
||||
const cssVar = useThemeCssVar(['contentPadding', 'borderColor', 'headerHeight', 'iconColorHover'])
|
||||
|
||||
return () => (
|
||||
@@ -28,26 +28,7 @@ export default defineComponent({
|
||||
{$t('t_0_1745289355714')}
|
||||
</NButton>
|
||||
),
|
||||
headerRight: () => (
|
||||
<NInput
|
||||
v-model:value={param.value.search}
|
||||
onKeydown={(e: KeyboardEvent) => {
|
||||
if (e.key === 'Enter') fetch()
|
||||
}}
|
||||
onClear={() => useTimeoutFn(() => fetch(), 100)}
|
||||
placeholder={$t('t_0_1745289808449')}
|
||||
clearable
|
||||
size="large"
|
||||
class="min-w-[300px]"
|
||||
v-slots={{
|
||||
suffix: () => (
|
||||
<div class="flex items-center cursor-pointer" onClick={fetch}>
|
||||
<Search class="text-[var(--text-color-3)] w-[1.6rem] font-bold" />
|
||||
</div>
|
||||
),
|
||||
}}
|
||||
/>
|
||||
),
|
||||
headerRight: () => <SearchComponent placeholder={$t('t_0_1745289808449')} />,
|
||||
content: () => (
|
||||
<div class="rounded-lg">
|
||||
<TableComponent
|
||||
@@ -60,15 +41,7 @@ export default defineComponent({
|
||||
),
|
||||
footerRight: () => (
|
||||
<div class="mt-4 flex justify-end">
|
||||
<PageComponent
|
||||
v-slots={{
|
||||
prefix: () => (
|
||||
<span>
|
||||
{$t('t_15_1745227839354')} {total.value} {$t('t_16_1745227838930')}
|
||||
</span>
|
||||
),
|
||||
}}
|
||||
/>
|
||||
<PageComponent />
|
||||
</div>
|
||||
),
|
||||
}}
|
||||
|
||||
@@ -20,6 +20,7 @@ import {
|
||||
useModal,
|
||||
useDialog,
|
||||
useTable,
|
||||
useSearch,
|
||||
useModalHooks,
|
||||
useFormHooks,
|
||||
useForm,
|
||||
@@ -64,11 +65,11 @@ import { JSX } from 'vue/jsx-runtime'
|
||||
*/
|
||||
interface AuthApiManageControllerExposes {
|
||||
loading: Ref<boolean>
|
||||
fetch: () => Promise<void>
|
||||
fetch: (resetPage?: boolean) => Promise<void>
|
||||
TableComponent: (props: Record<string, unknown>, context: Record<string, unknown>) => VNode
|
||||
PageComponent: (props: Record<string, unknown>, context: Record<string, unknown>) => VNode
|
||||
SearchComponent: (props: Record<string, unknown>, context: Record<string, unknown>) => VNode
|
||||
param: Ref<AccessListParams>
|
||||
total: Ref<number>
|
||||
openAddForm: () => void
|
||||
}
|
||||
|
||||
@@ -183,7 +184,7 @@ export const useController = (): AuthApiManageControllerExposes => {
|
||||
]
|
||||
|
||||
// 表格实例
|
||||
const { TableComponent, PageComponent, loading, param, total, fetch } = useTable<AccessItem, AccessListParams>({
|
||||
const { TableComponent, PageComponent, loading, param, fetch } = useTable<AccessItem, AccessListParams>({
|
||||
config: createColumns(),
|
||||
request: fetchAccessList,
|
||||
watchValue: ['p', 'limit'],
|
||||
@@ -196,6 +197,14 @@ export const useController = (): AuthApiManageControllerExposes => {
|
||||
},
|
||||
})
|
||||
|
||||
// 搜索实例
|
||||
const { SearchComponent, search } = useSearch({
|
||||
onSearch: (value) => {
|
||||
param.value.search = value
|
||||
fetch()
|
||||
},
|
||||
})
|
||||
|
||||
/**
|
||||
* 打开添加授权API弹窗
|
||||
*/
|
||||
@@ -255,8 +264,8 @@ export const useController = (): AuthApiManageControllerExposes => {
|
||||
fetch,
|
||||
TableComponent,
|
||||
PageComponent,
|
||||
SearchComponent,
|
||||
param,
|
||||
total,
|
||||
openAddForm,
|
||||
}
|
||||
}
|
||||
@@ -403,32 +412,32 @@ export const useApiFormController = (props: ApiFormControllerProps): ApiFormCont
|
||||
message: $t('t_0_1747617113090'),
|
||||
trigger: 'input',
|
||||
},
|
||||
access_key_id: {
|
||||
trigger: 'input',
|
||||
validator: (rule: FormItemRule, value: string, callback: (error?: Error) => void) => {
|
||||
if (!value) {
|
||||
const mapTips = {
|
||||
aliyun: $t('t_4_1745317314054'),
|
||||
doge: '请输入多吉云AccessKeyId',
|
||||
}
|
||||
return callback(new Error(mapTips[param.value.type as keyof typeof mapTips] || $t('t_4_1745317314054')))
|
||||
}
|
||||
callback()
|
||||
},
|
||||
},
|
||||
access_key_secret: {
|
||||
trigger: 'input',
|
||||
validator: (rule: FormItemRule, value: string, callback: (error?: Error) => void) => {
|
||||
if (!value) {
|
||||
const mapTips = {
|
||||
aliyun: $t('t_5_1745317315285'),
|
||||
doge: '请输入多吉云AccessKeySecret',
|
||||
}
|
||||
return callback(new Error(mapTips[param.value.type as keyof typeof mapTips] || $t('t_5_1745317315285')))
|
||||
}
|
||||
callback()
|
||||
},
|
||||
},
|
||||
// access_key_id: {
|
||||
// trigger: 'input',
|
||||
// validator: (rule: FormItemRule, value: string, callback: (error?: Error) => void) => {
|
||||
// if (!value) {
|
||||
// const mapTips = {
|
||||
// aliyun: $t('t_4_1745317314054'),
|
||||
// doge: '请输入多吉云AccessKeyId',
|
||||
// }
|
||||
// return callback(new Error(mapTips[param.value.type as keyof typeof mapTips] || $t('t_4_1745317314054')))
|
||||
// }
|
||||
// callback()
|
||||
// },
|
||||
// },
|
||||
// access_key_secret: {
|
||||
// trigger: 'input',
|
||||
// validator: (rule: FormItemRule, value: string, callback: (error?: Error) => void) => {
|
||||
// if (!value) {
|
||||
// const mapTips = {
|
||||
// aliyun: $t('t_5_1745317315285'),
|
||||
// doge: '请输入多吉云AccessKeySecret',
|
||||
// }
|
||||
// return callback(new Error(mapTips[param.value.type as keyof typeof mapTips] || $t('t_5_1745317315285')))
|
||||
// }
|
||||
// callback()
|
||||
// },
|
||||
// },
|
||||
secret_access_key: {
|
||||
required: true,
|
||||
message: '请输入Secret Access Key',
|
||||
@@ -478,6 +487,7 @@ export const useApiFormController = (props: ApiFormControllerProps): ApiFormCont
|
||||
baidu: $t('t_3_1747271294475'),
|
||||
volcengine: $t('t_3_1747365600828'),
|
||||
qiniu: $t('t_3_1747984134586'),
|
||||
doge: $t('t_0_1750320239265'),
|
||||
}
|
||||
return callback(new Error(mapTips[param.value.type as keyof typeof mapTips]))
|
||||
}
|
||||
@@ -493,6 +503,7 @@ export const useApiFormController = (props: ApiFormControllerProps): ApiFormCont
|
||||
huawei: $t('t_3_1747042967608'),
|
||||
baidu: $t('t_4_1747271294621'),
|
||||
volcengine: $t('t_4_1747365600137'),
|
||||
doge: $t('t_1_1750320241427'),
|
||||
}
|
||||
return callback(new Error(mapTips[param.value.type as keyof typeof mapTips]))
|
||||
}
|
||||
@@ -632,6 +643,7 @@ export const useApiFormController = (props: ApiFormControllerProps): ApiFormCont
|
||||
case 'huaweicloud':
|
||||
case 'baidu':
|
||||
case 'volcengine':
|
||||
case 'doge':
|
||||
items.push(
|
||||
useFormInput('AccessKey', 'config.access_key', { allowInput: noSideSpace }),
|
||||
useFormInput('SecretKey', 'config.secret_key', { allowInput: noSideSpace }),
|
||||
@@ -711,12 +723,6 @@ export const useApiFormController = (props: ApiFormControllerProps): ApiFormCont
|
||||
useFormInput('Secret Access Key', 'config.secret_access_key', { allowInput: noSideSpace }),
|
||||
)
|
||||
break
|
||||
case 'doge':
|
||||
items.push(
|
||||
useFormInput('AccessKeyId', 'config.access_key_id', { allowInput: noSideSpace }),
|
||||
useFormInput('AccessKeySecret', 'config.access_key_secret', { allowInput: noSideSpace }),
|
||||
)
|
||||
break
|
||||
case 'plugin':
|
||||
items.push(
|
||||
useFormCustom(() => {
|
||||
@@ -743,39 +749,39 @@ export const useApiFormController = (props: ApiFormControllerProps): ApiFormCont
|
||||
</NFormItem>
|
||||
)
|
||||
}),
|
||||
useFormCustom(() => {
|
||||
const pluginConfig = param.value.config as PluginAccessConfig
|
||||
const getConfigValue = () => {
|
||||
return typeof pluginConfig.config === 'string'
|
||||
? pluginConfig.config
|
||||
: JSON.stringify(pluginConfig.config, null, 2)
|
||||
}
|
||||
return (
|
||||
<NFormItem
|
||||
path="config.params"
|
||||
v-slots={{
|
||||
label: () => (
|
||||
<div>
|
||||
<NText>自定义参数</NText>
|
||||
<NTooltip
|
||||
v-slots={{
|
||||
trigger: () => (
|
||||
<span class="inline-flex ml-2 -mt-1 cursor-pointer text-base rounded-full w-[14px] h-[14px] justify-center items-center text-orange-600 border border-orange-600">
|
||||
?
|
||||
</span>
|
||||
),
|
||||
}}
|
||||
>
|
||||
{pluginActionTips.value}
|
||||
</NTooltip>
|
||||
</div>
|
||||
),
|
||||
}}
|
||||
>
|
||||
<NInput type="textarea" value={getConfigValue()} placeholder={pluginActionTips.value} rows={4} />
|
||||
</NFormItem>
|
||||
)
|
||||
}),
|
||||
useFormCustom(() => {
|
||||
const pluginConfig = param.value.config as PluginAccessConfig
|
||||
const getConfigValue = () => {
|
||||
return typeof pluginConfig.config === 'string'
|
||||
? pluginConfig.config
|
||||
: JSON.stringify(pluginConfig.config, null, 2)
|
||||
}
|
||||
return (
|
||||
<NFormItem
|
||||
path="config.params"
|
||||
v-slots={{
|
||||
label: () => (
|
||||
<div>
|
||||
<NText>自定义参数</NText>
|
||||
<NTooltip
|
||||
v-slots={{
|
||||
trigger: () => (
|
||||
<span class="inline-flex ml-2 -mt-1 cursor-pointer text-base rounded-full w-[14px] h-[14px] justify-center items-center text-orange-600 border border-orange-600">
|
||||
?
|
||||
</span>
|
||||
),
|
||||
}}
|
||||
>
|
||||
{pluginActionTips.value}
|
||||
</NTooltip>
|
||||
</div>
|
||||
),
|
||||
}}
|
||||
>
|
||||
<NInput type="textarea" value={getConfigValue()} placeholder={pluginActionTips.value} rows={4} />
|
||||
</NFormItem>
|
||||
)
|
||||
}),
|
||||
)
|
||||
break
|
||||
default:
|
||||
@@ -904,8 +910,8 @@ export const useApiFormController = (props: ApiFormControllerProps): ApiFormCont
|
||||
break
|
||||
case 'doge':
|
||||
param.value.config = {
|
||||
access_key_id: '',
|
||||
access_key_secret: '',
|
||||
access_key: '',
|
||||
secret_key: '',
|
||||
} as DogeAccessConfig
|
||||
break
|
||||
case 'plugin':
|
||||
|
||||
@@ -189,6 +189,13 @@ export function createNodeFormConfig() {
|
||||
]
|
||||
},
|
||||
|
||||
/**
|
||||
* 创建阿里云ESA相关字段
|
||||
*/
|
||||
aliyunEsaDeploy() {
|
||||
return [this.input('站点ID', 'site_id', { placeholder: '请输入ESA站点ID' })]
|
||||
},
|
||||
|
||||
/**
|
||||
* 创建跳过选项字段
|
||||
* @param valueRef 值引用
|
||||
|
||||
@@ -1,13 +1,29 @@
|
||||
import { NFormItem, NInputNumber, NSwitch } from 'naive-ui'
|
||||
import {
|
||||
NFormItem,
|
||||
NInputNumber,
|
||||
NSwitch,
|
||||
NSelect,
|
||||
NAutoComplete,
|
||||
NInput,
|
||||
NFlex,
|
||||
NText,
|
||||
NButton,
|
||||
NGrid,
|
||||
NFormItemGi,
|
||||
NSpin,
|
||||
NDropdown,
|
||||
} from 'naive-ui'
|
||||
import { useForm, useFormHooks, useModalHooks } from '@baota/naive-ui/hooks'
|
||||
import { useStore } from '@components/FlowChart/useStore'
|
||||
import { $t } from '@locales/index'
|
||||
import rules from './verify'
|
||||
import DnsProviderSelect from '@components/DnsProviderSelect'
|
||||
import CAProviderSelect from '@components/CAProviderSelect'
|
||||
import type { ApplyNodeConfig } from '@components/FlowChart/types'
|
||||
import { deepClone } from '@baota/utils/data'
|
||||
import { noSideSpace } from '@lib/utils'
|
||||
import { getEabList } from '@api/access'
|
||||
import SvgIcon from '@components/SvgIcon'
|
||||
import { CACertificateAuthorization } from '@config/data'
|
||||
|
||||
export default defineComponent({
|
||||
name: 'ApplyNodeDrawer',
|
||||
@@ -45,6 +61,150 @@ export default defineComponent({
|
||||
// 表单参数
|
||||
const param = ref(deepClone(props.node.config))
|
||||
|
||||
// CA选项状态
|
||||
const caOptions = ref<Array<{ label: string; value: string; icon: string }>>([])
|
||||
const emailOptions = ref<string[]>([])
|
||||
const isLoadingCA = ref(false)
|
||||
const isLoadingEmails = ref(false)
|
||||
const showEmailDropdown = ref(false)
|
||||
const emailInputRef = ref<any>(null)
|
||||
|
||||
// 加载CA选项
|
||||
const loadCAOptions = async () => {
|
||||
isLoadingCA.value = true
|
||||
try {
|
||||
const { data } = await getEabList({ ca: '', p: 1, limit: 1000 }).fetch()
|
||||
const uniqueCATypes = new Set<string>()
|
||||
const caList: Array<{ label: string; value: string; icon: string }> = []
|
||||
|
||||
// 优先添加重要的CA类型(确保始终显示)
|
||||
const priorityCATypes = ['letsencrypt', 'buypass', 'zerossl']
|
||||
priorityCATypes.forEach((caType) => {
|
||||
if (!uniqueCATypes.has(caType)) {
|
||||
uniqueCATypes.add(caType)
|
||||
const predefinedCA = Object.values(CACertificateAuthorization).find((ca) => ca.type === caType)
|
||||
caList.push({
|
||||
label: predefinedCA ? predefinedCA.name : caType.toUpperCase(),
|
||||
value: caType,
|
||||
icon: `cert-${caType}`,
|
||||
})
|
||||
}
|
||||
})
|
||||
|
||||
// 添加API返回的其他CA类型(去重)
|
||||
data?.forEach((item) => {
|
||||
if (item.ca && !uniqueCATypes.has(item.ca)) {
|
||||
uniqueCATypes.add(item.ca)
|
||||
|
||||
// 查找预定义配置中对应的CA信息
|
||||
const predefinedCA = Object.values(CACertificateAuthorization).find((ca) => ca.type === item.ca)
|
||||
caList.push({
|
||||
label: predefinedCA ? predefinedCA.name : item.ca.toUpperCase(),
|
||||
value: item.ca,
|
||||
icon: predefinedCA ? `cert-${item.ca}` : 'cert-custom', // 如果不在预定义配置中,使用custom图标;否则使用对应的cert图标
|
||||
})
|
||||
}
|
||||
})
|
||||
|
||||
caOptions.value = caList
|
||||
} catch (error) {
|
||||
console.error('加载CA选项失败:', error)
|
||||
} finally {
|
||||
isLoadingCA.value = false
|
||||
}
|
||||
}
|
||||
|
||||
// 加载邮件选项
|
||||
const loadEmailOptions = async (ca: string) => {
|
||||
if (!ca) return
|
||||
isLoadingEmails.value = true
|
||||
try {
|
||||
const { data } = await getEabList({ ca, p: 1, limit: 1000 }).fetch()
|
||||
emailOptions.value = data?.map((item) => item.email).filter(Boolean) || []
|
||||
if (!emailOptions.value.length) {
|
||||
param.value.email = ''
|
||||
}
|
||||
// 如果邮箱数组有内容且当前邮箱为空,自动填充第一个邮箱地址
|
||||
if (emailOptions.value.length > 0 && emailOptions.value[0]) {
|
||||
param.value.email = emailOptions.value[0]
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('加载邮件选项失败:', error)
|
||||
} finally {
|
||||
isLoadingEmails.value = false
|
||||
}
|
||||
}
|
||||
|
||||
// 处理CA选择变化
|
||||
const handleCAChange = (value: string) => {
|
||||
param.value.ca = value
|
||||
loadEmailOptions(value)
|
||||
}
|
||||
|
||||
// 跳转到CA管理页面
|
||||
const goToAddCAProvider = () => {
|
||||
window.open('/auto-deploy?type=caManage', '_blank')
|
||||
}
|
||||
|
||||
// 渲染CA选择器标签
|
||||
const renderLabel = (option: { label: string; value: string; icon: string }) => {
|
||||
return (
|
||||
<NFlex align="center">
|
||||
<SvgIcon icon={option.icon} size="2rem" />
|
||||
<NText>{option.label}</NText>
|
||||
</NFlex>
|
||||
)
|
||||
}
|
||||
|
||||
// 渲染CA选择器单选标签
|
||||
const renderSingleSelectTag = ({ option }: { option: any }) => {
|
||||
return (
|
||||
<NFlex align="center">
|
||||
{option.label ? renderLabel(option) : <NText class="text-[#aaa]">{$t('t_0_1747990228780')}</NText>}
|
||||
</NFlex>
|
||||
)
|
||||
}
|
||||
|
||||
// 过滤函数
|
||||
const handleFilter = (pattern: string, option: any): boolean => {
|
||||
return option.label.toLowerCase().includes(pattern.toLowerCase())
|
||||
}
|
||||
|
||||
// 处理邮箱输入框焦点
|
||||
const handleEmailFocus = () => {
|
||||
if (emailOptions.value.length > 0) {
|
||||
showEmailDropdown.value = true
|
||||
}
|
||||
}
|
||||
|
||||
// 处理邮箱输入框失焦
|
||||
const handleEmailBlur = () => {
|
||||
// 延迟关闭下拉,确保点击选项有时间触发
|
||||
setTimeout(() => {
|
||||
showEmailDropdown.value = false
|
||||
}, 200)
|
||||
}
|
||||
|
||||
// 选择邮箱地址
|
||||
const handleSelectEmail = (email: string) => {
|
||||
param.value.email = email
|
||||
showEmailDropdown.value = false
|
||||
emailInputRef.value?.blur()
|
||||
}
|
||||
|
||||
// 创建邮箱下拉选项
|
||||
const emailDropdownOptions = computed(() => {
|
||||
return emailOptions.value.map((email) => ({
|
||||
label: email,
|
||||
key: email,
|
||||
}))
|
||||
})
|
||||
|
||||
// 判断是否需要输入框(letsencrypt、buypass、zerossl)
|
||||
const shouldUseInputForEmail = computed(() => {
|
||||
return ['letsencrypt', 'buypass', 'zerossl'].includes(param.value.ca)
|
||||
})
|
||||
|
||||
// 表单渲染配置
|
||||
const config = computed(() => {
|
||||
// 基本选项
|
||||
@@ -80,27 +240,80 @@ export default defineComponent({
|
||||
type: 'custom' as const,
|
||||
render: () => {
|
||||
return (
|
||||
<CAProviderSelect
|
||||
path="eabId"
|
||||
value={param.value.eabId}
|
||||
email={param.value.email}
|
||||
ca={param.value.ca}
|
||||
{...{
|
||||
'onUpdate:value': (val: { value: string; ca: string; email: string }) => {
|
||||
param.value.eabId = val.value
|
||||
param.value.ca = val.ca
|
||||
// 始终更新邮件,确保 Let's Encrypt 和 Buypass 的邮件能正确显示
|
||||
param.value.email = val.email
|
||||
},
|
||||
}}
|
||||
/>
|
||||
<NSpin show={isLoadingCA.value}>
|
||||
<NGrid cols={24}>
|
||||
<NFormItemGi span={13} label={$t('证书CA')} path="ca" showRequireMark={true}>
|
||||
<NSelect
|
||||
value={param.value.ca}
|
||||
options={caOptions.value}
|
||||
renderLabel={renderLabel}
|
||||
renderTag={renderSingleSelectTag}
|
||||
filterable
|
||||
filter={handleFilter}
|
||||
loading={isLoadingCA.value}
|
||||
placeholder={$t('t_0_1747990228780')}
|
||||
onUpdateValue={handleCAChange}
|
||||
class="flex-1 w-full"
|
||||
v-slots={{
|
||||
empty: () => {
|
||||
return <span class="text-[1.4rem]">{$t('t_2_1747990228008')}</span>
|
||||
},
|
||||
}}
|
||||
/>
|
||||
</NFormItemGi>
|
||||
<NFormItemGi span={11}>
|
||||
<NButton class="mx-[8px]" onClick={goToAddCAProvider}>
|
||||
{$t('添加CA授权')}
|
||||
</NButton>
|
||||
<NButton onClick={loadCAOptions} loading={isLoadingCA.value}>
|
||||
{$t('t_0_1746497662220')}
|
||||
</NButton>
|
||||
</NFormItemGi>
|
||||
</NGrid>
|
||||
</NSpin>
|
||||
)
|
||||
},
|
||||
},
|
||||
{
|
||||
type: 'custom' as const,
|
||||
render: () => {
|
||||
return (
|
||||
<NFormItem label={$t('t_68_1745289354676')} path="email">
|
||||
{shouldUseInputForEmail.value ? (
|
||||
<NDropdown
|
||||
trigger="manual"
|
||||
show={showEmailDropdown.value}
|
||||
options={emailDropdownOptions.value}
|
||||
onSelect={handleSelectEmail}
|
||||
placement="bottom-start"
|
||||
style="width: 100%"
|
||||
>
|
||||
<NInput
|
||||
ref={emailInputRef}
|
||||
v-model:value={param.value.email}
|
||||
placeholder={$t('t_2_1748052862259')}
|
||||
clearable
|
||||
loading={isLoadingEmails.value}
|
||||
onFocus={handleEmailFocus}
|
||||
onBlur={handleEmailBlur}
|
||||
class="w-full"
|
||||
/>
|
||||
</NDropdown>
|
||||
) : (
|
||||
<NSelect
|
||||
v-model:value={param.value.email}
|
||||
options={emailOptions.value.map((email) => ({ label: email, value: email }))}
|
||||
placeholder={$t('t_2_1748052862259')}
|
||||
clearable
|
||||
filterable
|
||||
loading={isLoadingEmails.value}
|
||||
class="w-full"
|
||||
/>
|
||||
)}
|
||||
</NFormItem>
|
||||
)
|
||||
},
|
||||
},
|
||||
useFormInput($t('t_68_1745289354676'), 'email', {
|
||||
placeholder: $t('t_2_1748052862259'),
|
||||
allowInput: noSideSpace,
|
||||
}),
|
||||
|
||||
{
|
||||
type: 'custom' as const,
|
||||
@@ -232,8 +445,37 @@ export default defineComponent({
|
||||
// 创建表单实例
|
||||
const { component: Form, data, example } = useForm<ApplyNodeConfig>({ defaultValue: param, config, rules })
|
||||
|
||||
onMounted(() => {
|
||||
// 监听CA值变化,自动加载邮箱选项
|
||||
watch(
|
||||
() => param.value.ca,
|
||||
async (newCA) => {
|
||||
if (newCA) {
|
||||
await loadEmailOptions(newCA)
|
||||
} else {
|
||||
emailOptions.value = []
|
||||
param.value.email = ''
|
||||
showEmailDropdown.value = false
|
||||
}
|
||||
},
|
||||
)
|
||||
|
||||
// 监听邮箱选项变化,如果当前下拉显示且没有选项了就关闭下拉
|
||||
watch(
|
||||
() => emailOptions.value,
|
||||
(newOptions) => {
|
||||
if (showEmailDropdown.value && newOptions.length === 0) {
|
||||
showEmailDropdown.value = false
|
||||
}
|
||||
},
|
||||
)
|
||||
|
||||
onMounted(async () => {
|
||||
advancedOptions.value = false
|
||||
await loadCAOptions()
|
||||
// 如果初始化时已有CA值,加载对应的邮箱选项
|
||||
if (param.value.ca) {
|
||||
await loadEmailOptions(param.value.ca)
|
||||
}
|
||||
})
|
||||
|
||||
// 确认事件触发
|
||||
|
||||
@@ -225,6 +225,9 @@ export default defineComponent({
|
||||
case 'aliyun-oss':
|
||||
config.push(...formConfig.storageDeploy())
|
||||
break
|
||||
case 'aliyun-esa':
|
||||
config.push(...formConfig.aliyunEsaDeploy())
|
||||
break
|
||||
case 'plugin':
|
||||
// 插件部署配置
|
||||
config.push(
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { FormRules } from 'naive-ui'
|
||||
import { $t } from '@locales/index'
|
||||
import { createNodeValidator } from '@workflowView/lib/NodeValidator'
|
||||
import { isDomain } from '@baota/utils/business'
|
||||
import { isDomain, isWildcardDomain } from '@baota/utils/business'
|
||||
|
||||
// 创建部署节点验证器
|
||||
const validator = createNodeValidator($t('t_11_1747817612051'))
|
||||
@@ -51,7 +51,7 @@ export default {
|
||||
if (!value) {
|
||||
return new Error($t('t_0_1744958839535'))
|
||||
}
|
||||
if (!isDomain(value)) {
|
||||
if (!isWildcardDomain(value)) {
|
||||
return new Error($t('t_0_1744958839535'))
|
||||
}
|
||||
return true
|
||||
|
||||
@@ -11,6 +11,7 @@ import verify from './verify'
|
||||
import { NotifyNodeConfig } from '@components/FlowChart/types'
|
||||
import { deepClone } from '@baota/utils/data'
|
||||
import { noSideSpace } from '@lib/utils'
|
||||
import { NSwitch, NFormItem, NText } from 'naive-ui'
|
||||
|
||||
export default defineComponent({
|
||||
name: 'NotifyNodeDrawer',
|
||||
@@ -25,6 +26,7 @@ export default defineComponent({
|
||||
provider_id: '',
|
||||
subject: '',
|
||||
body: '',
|
||||
skip: false,
|
||||
},
|
||||
}),
|
||||
},
|
||||
@@ -36,6 +38,14 @@ export default defineComponent({
|
||||
const { handleError } = useError()
|
||||
const param = ref(deepClone(props.node.config))
|
||||
|
||||
// 创建一个用于开关的响应式值(发送通知的状态)
|
||||
const shouldSendNotify = computed({
|
||||
get: () => !param.value.skip,
|
||||
set: (value: boolean) => {
|
||||
param.value.skip = !value
|
||||
},
|
||||
})
|
||||
|
||||
// 表单渲染配置
|
||||
const formConfig: FormConfig = [
|
||||
useFormInput($t('t_0_1745920566646'), 'subject', {
|
||||
@@ -58,6 +68,21 @@ export default defineComponent({
|
||||
}}
|
||||
/>
|
||||
)),
|
||||
useFormCustom(() => (
|
||||
<NFormItem label={$t('t_2_1750320237611')} path="skip">
|
||||
<NText>当结果来源为跳过状态时</NText>
|
||||
<NSwitch
|
||||
v-model:value={shouldSendNotify.value}
|
||||
checkedValue={true}
|
||||
uncheckedValue={false}
|
||||
class="mx-[.5rem]"
|
||||
v-slots={{
|
||||
checked: () => $t('t_3_1750320237991'),
|
||||
unchecked: () => $t('t_11_1747280809178'),
|
||||
}}
|
||||
/>
|
||||
</NFormItem>
|
||||
)),
|
||||
]
|
||||
|
||||
// 创建表单实例
|
||||
|
||||
@@ -11,6 +11,7 @@ import type { FormConfig } from '@baota/naive-ui/types/form'
|
||||
import type { VNode } from 'vue'
|
||||
import { useError } from '@baota/hooks/error'
|
||||
import { deepClone } from '@baota/utils/data'
|
||||
import { isUndefined } from '@baota/utils/type'
|
||||
|
||||
export default defineComponent({
|
||||
name: 'StartNodeDrawer',
|
||||
@@ -27,7 +28,7 @@ export default defineComponent({
|
||||
},
|
||||
},
|
||||
setup(props) {
|
||||
const { updateNodeConfig, isRefreshNode } = useStore()
|
||||
const { updateNodeConfig, isRefreshNode, flowData } = useStore()
|
||||
// 弹窗辅助
|
||||
const { confirm } = useModalHooks()
|
||||
// 错误处理
|
||||
@@ -90,7 +91,17 @@ export default defineComponent({
|
||||
return (
|
||||
<NGrid cols={24} xGap={24}>
|
||||
<NFormItemGi label={$t('t_2_1744879616413')} span={8} showRequireMark path="type">
|
||||
<NSelect class="w-full" options={cycleTypeOptions} v-model:value={param.value.type} />
|
||||
<NSelect
|
||||
class="w-full"
|
||||
options={cycleTypeOptions}
|
||||
v-model:value={param.value.type}
|
||||
onUpdateValue={(val: 'day' | 'week' | 'month') => {
|
||||
if (val) {
|
||||
param.value.type = val
|
||||
updateParamValueByType(val)
|
||||
}
|
||||
}}
|
||||
/>
|
||||
</NFormItemGi>
|
||||
|
||||
{param.value.type !== 'day' && (
|
||||
@@ -99,9 +110,7 @@ export default defineComponent({
|
||||
<NSelect
|
||||
value={param.value.week}
|
||||
onUpdateValue={(val: number) => {
|
||||
if (typeof val === 'number') {
|
||||
param.value.week = val
|
||||
}
|
||||
param.value.week = val
|
||||
}}
|
||||
options={weekOptions}
|
||||
/>
|
||||
@@ -161,19 +170,24 @@ export default defineComponent({
|
||||
|
||||
// 更新参数的函数
|
||||
const updateParamValue = (updates: StartNodeConfig) => {
|
||||
console.log(updates)
|
||||
let newParams = { ...updates }
|
||||
if (newParams.exec_type === 'manual') {
|
||||
// 小时随机 1-6
|
||||
const randomHour = Math.floor(Math.random() * 6) + 1
|
||||
// 分钟每5分钟随机,0-55
|
||||
const randomMinute = Math.floor(Math.random() * 12) * 5
|
||||
newParams = {
|
||||
...newParams,
|
||||
hour: randomHour,
|
||||
minute: randomMinute,
|
||||
}
|
||||
param.value = newParams
|
||||
// if (newParams.exec_type === 'manual') {
|
||||
// 小时随机 1-6
|
||||
const randomHour = Math.floor(Math.random() * 4) + 1
|
||||
// 分钟每5分钟随机,0-55
|
||||
const randomMinute = Math.floor(Math.random() * 12) * 5
|
||||
newParams = {
|
||||
...newParams,
|
||||
hour: randomHour,
|
||||
minute: randomMinute,
|
||||
}
|
||||
param.value = newParams
|
||||
// }
|
||||
}
|
||||
|
||||
const updateParamValueByType = (type: 'day' | 'week' | 'month') => {
|
||||
updateParamValue(DEFAULT_AUTO_SETTINGS[type] as StartNodeConfig)
|
||||
}
|
||||
|
||||
// 监听执行类型变化
|
||||
@@ -210,6 +224,13 @@ export default defineComponent({
|
||||
}
|
||||
})
|
||||
|
||||
onMounted(() => {
|
||||
if (isUndefined(flowData.value.id)) {
|
||||
updateParamValueByType('day')
|
||||
updateNodeConfig(props.node.id, param.value) // 更新节点配置
|
||||
}
|
||||
})
|
||||
|
||||
return () => (
|
||||
<div class="apply-node-drawer">
|
||||
<Form labelPlacement="top" />
|
||||
|
||||
@@ -18,7 +18,7 @@ export default defineComponent({
|
||||
},
|
||||
},
|
||||
setup(props) {
|
||||
const { TableComponent, PageComponent, handleOpenAddForm, total } = useCAManageController(props)
|
||||
const { TableComponent, PageComponent, handleOpenAddForm } = useCAManageController(props)
|
||||
return () => (
|
||||
<BaseComponent
|
||||
v-slots={{
|
||||
@@ -40,15 +40,7 @@ export default defineComponent({
|
||||
),
|
||||
footerRight: () => (
|
||||
<div class="flex justify-end mt-4">
|
||||
<PageComponent
|
||||
v-slots={{
|
||||
prefix: () => (
|
||||
<span>
|
||||
{$t('t_15_1745227839354')} {total.value} {$t('t_16_1745227838930')}
|
||||
</span>
|
||||
),
|
||||
}}
|
||||
/>
|
||||
<PageComponent />
|
||||
</div>
|
||||
),
|
||||
}}
|
||||
|
||||
@@ -18,15 +18,14 @@ export default defineComponent({
|
||||
const {
|
||||
TableComponent,
|
||||
PageComponent,
|
||||
SearchComponent,
|
||||
isDetectionAddWorkflow,
|
||||
isDetectionOpenCAManage,
|
||||
isDetectionOpenAddCAForm,
|
||||
handleAddWorkflow,
|
||||
handleOpenCAManage,
|
||||
hasChildRoutes,
|
||||
param,
|
||||
fetch,
|
||||
data,
|
||||
} = useController()
|
||||
const router = useRouter()
|
||||
// 获取主题变量
|
||||
@@ -65,26 +64,7 @@ export default defineComponent({
|
||||
</NButton>
|
||||
</NSpace>
|
||||
),
|
||||
headerRight: () => (
|
||||
<NInput
|
||||
v-model:value={param.value.search}
|
||||
onKeydown={(e: KeyboardEvent) => {
|
||||
if (e.key === 'Enter') fetch()
|
||||
}}
|
||||
onClear={() => useTimeoutFn(fetch, 100)}
|
||||
placeholder={$t('t_1_1745227838776')}
|
||||
clearable
|
||||
size="large"
|
||||
class="min-w-[300px]"
|
||||
v-slots={{
|
||||
suffix: () => (
|
||||
<div class="flex items-center" onClick={fetch}>
|
||||
<Search class="text-[var(--text-color-3)] w-[1.6rem] cursor-pointer font-bold" />
|
||||
</div>
|
||||
),
|
||||
}}
|
||||
></NInput>
|
||||
),
|
||||
headerRight: () => <SearchComponent placeholder={$t('t_1_1745227838776')} />,
|
||||
content: () => (
|
||||
<div class="rounded-lg ">
|
||||
<TableComponent
|
||||
@@ -99,11 +79,7 @@ export default defineComponent({
|
||||
),
|
||||
footerRight: () => (
|
||||
<div class="mt-4 flex justify-end">
|
||||
<PageComponent
|
||||
v-slots={{
|
||||
prefix: () => <span>{$t('t_0_1746773350551', [data.value.total])}</span>,
|
||||
}}
|
||||
/>
|
||||
<PageComponent />
|
||||
</div>
|
||||
),
|
||||
}}
|
||||
|
||||
@@ -1,7 +1,16 @@
|
||||
import { NSwitch, NTag, NButton, NSpace, NFlex, NText, NFormItem, NSelect } from 'naive-ui'
|
||||
import { useRoute, useRouter } from 'vue-router'
|
||||
import { useStore } from '@autoDeploy/useStore'
|
||||
import { useDialog, useTable, useModal, useFormHooks, useForm, useModalHooks, useMessage } from '@baota/naive-ui/hooks'
|
||||
import {
|
||||
useDialog,
|
||||
useTable,
|
||||
useModal,
|
||||
useFormHooks,
|
||||
useForm,
|
||||
useModalHooks,
|
||||
useMessage,
|
||||
useSearch,
|
||||
} from '@baota/naive-ui/hooks'
|
||||
import { useStore as useWorkflowViewStore } from '@autoDeploy/children/workflowView/useStore'
|
||||
import { useError } from '@baota/hooks/error'
|
||||
import AddWorkflowModal from './components/WorkflowModal'
|
||||
@@ -152,7 +161,7 @@ export const useController = () => {
|
||||
]
|
||||
|
||||
// 表格实例
|
||||
const { TableComponent, PageComponent, loading, param, data, fetch } = useTable<WorkflowItem, WorkflowListParams>({
|
||||
const { TableComponent, PageComponent, loading, param, fetch } = useTable<WorkflowItem, WorkflowListParams>({
|
||||
config: createColumns(),
|
||||
request: fetchWorkflowList,
|
||||
storage: 'autoDeployPageSize',
|
||||
@@ -161,6 +170,14 @@ export const useController = () => {
|
||||
watchValue: ['p', 'limit'],
|
||||
})
|
||||
|
||||
// 搜索实例
|
||||
const { SearchComponent } = useSearch({
|
||||
onSearch: (value) => {
|
||||
param.value.search = value
|
||||
fetch()
|
||||
},
|
||||
})
|
||||
|
||||
// 节流渲染
|
||||
const throttleFn = useThrottleFn(() => {
|
||||
setTimeout(() => {
|
||||
@@ -229,7 +246,7 @@ export const useController = () => {
|
||||
title: exec_type === 'manual' ? $t('t_2_1745457488661') : $t('t_3_1745457486983'),
|
||||
content: exec_type === 'manual' ? $t('t_4_1745457497303') : $t('t_5_1745457494695'),
|
||||
onPositiveClick: () => setWorkflowExecType({ id, exec_type }),
|
||||
onNegativeClick: fetch,
|
||||
onNegativeClick: () => fetch(),
|
||||
onClose: fetch,
|
||||
})
|
||||
}
|
||||
@@ -243,8 +260,8 @@ export const useController = () => {
|
||||
title: !active ? $t('t_6_1745457487560') : $t('t_7_1745457487185'),
|
||||
content: !active ? $t('t_8_1745457496621') : $t('t_9_1745457500045'),
|
||||
onPositiveClick: () => setWorkflowActive({ id, active }),
|
||||
onNegativeClick: fetch,
|
||||
onClose: fetch,
|
||||
onNegativeClick: () => fetch(),
|
||||
onClose: () => fetch(),
|
||||
})
|
||||
}
|
||||
|
||||
@@ -335,6 +352,7 @@ export const useController = () => {
|
||||
return {
|
||||
TableComponent,
|
||||
PageComponent,
|
||||
SearchComponent,
|
||||
isDetectionAddWorkflow, // 检测是否需要添加工作流
|
||||
isDetectionOpenCAManage, // 检测是否需要打开CA授权管理弹窗
|
||||
isDetectionOpenAddCAForm, // 检测是否需要打开添加CA授权弹窗
|
||||
@@ -348,7 +366,6 @@ export const useController = () => {
|
||||
handleOpenCAManage, // 打开CA授权管理弹窗
|
||||
hasChildRoutes,
|
||||
fetch,
|
||||
data,
|
||||
loading,
|
||||
param,
|
||||
}
|
||||
@@ -504,8 +521,14 @@ export const useHistoryController = (id: string) => {
|
||||
* @returns 返回CA授权类型名称
|
||||
*/
|
||||
const handleCertAuth = (type: string) => {
|
||||
const name = type.replaceAll('.', '').replaceAll("'", '').replaceAll(' ', '').toLowerCase() // 处理类型中的特殊字符
|
||||
return CACertificateAuthorization[name as keyof typeof CACertificateAuthorization].type
|
||||
// console.log(type)
|
||||
try {
|
||||
const name = type.replaceAll('.', '').replaceAll("'", '').replaceAll(' ', '').toLowerCase() // 处理类型中的特殊字符
|
||||
const caType = CACertificateAuthorization[name as keyof typeof CACertificateAuthorization].type
|
||||
return { type: caType, icon: type }
|
||||
} catch (error) {
|
||||
return { type, icon: 'custom' }
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -528,11 +551,11 @@ export const useCAManageController = (props: { type: string }) => {
|
||||
key: 'ca',
|
||||
width: 200,
|
||||
render: (row: EabItem) => {
|
||||
const name = handleCertAuth(row.ca)
|
||||
const { type, icon } = handleCertAuth(row.ca)
|
||||
return (
|
||||
<NFlex align="center">
|
||||
<SvgIcon icon={`cert-${name}`} size="2rem" />
|
||||
<NText>{name}</NText>
|
||||
<SvgIcon icon={`cert-${icon}`} size="2rem" />
|
||||
<NText>{type}</NText>
|
||||
</NFlex>
|
||||
)
|
||||
},
|
||||
@@ -606,10 +629,14 @@ export const useCAManageController = (props: { type: string }) => {
|
||||
* @param {EabItem} row - CA授权数据
|
||||
*/
|
||||
const handleEdit = (row: EabItem) => {
|
||||
const caTypes = Object.values(CACertificateAuthorization).map((item) => item.type)
|
||||
const isCustomCa = !caTypes.includes(row.ca)
|
||||
|
||||
// 填充表单数据 - 添加编辑模式标识
|
||||
Object.assign(caFormData.value, {
|
||||
email: row.email,
|
||||
ca: row.ca,
|
||||
ca: isCustomCa ? 'custom' : row.ca,
|
||||
caName: isCustomCa ? row.ca : '',
|
||||
Kid: row.Kid || '',
|
||||
HmacEncoded: row.HmacEncoded || '',
|
||||
CADirURL: row.CADirURL || '',
|
||||
@@ -666,7 +693,6 @@ export const useCAManageController = (props: { type: string }) => {
|
||||
*/
|
||||
export const useCAFormController = (props?: { isEdit?: boolean; editId?: string }) => {
|
||||
const { handleError } = useError()
|
||||
const message = useMessage()
|
||||
const { confirm } = useModalHooks()
|
||||
const { useFormInput, useFormCustom } = useFormHooks()
|
||||
|
||||
@@ -710,10 +736,26 @@ export const useCAFormController = (props?: { isEdit?: boolean; editId?: string
|
||||
|
||||
// 自定义类型必填 CADirURL
|
||||
if (currentCa === 'custom') {
|
||||
rules.caName = {
|
||||
required: true,
|
||||
message: '请输入CA名称',
|
||||
trigger: ['blur', 'input'],
|
||||
}
|
||||
rules.CADirURL = {
|
||||
required: true,
|
||||
message: $t('t_4_1750129259795'),
|
||||
trigger: ['blur', 'input'],
|
||||
validator: (rule: any, value: string) => {
|
||||
if (!value) {
|
||||
return new Error('请输入CA目录URL')
|
||||
}
|
||||
// Basic URL validation
|
||||
try {
|
||||
new URL(value)
|
||||
return true
|
||||
} catch (e) {
|
||||
return new Error('请输入有效的URL地址')
|
||||
}
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
@@ -769,9 +811,6 @@ export const useCAFormController = (props?: { isEdit?: boolean; editId?: string
|
||||
|
||||
// 表单配置
|
||||
const formConfig = computed(() => [
|
||||
useFormInput($t('t_1_1745735764953'), 'email', {
|
||||
placeholder: $t('t_0_1747965909665'),
|
||||
}),
|
||||
useFormCustom(() => {
|
||||
return (
|
||||
<NFormItem label={$t('t_9_1747903669360')} path="ca">
|
||||
@@ -792,11 +831,17 @@ export const useCAFormController = (props?: { isEdit?: boolean; editId?: string
|
||||
</NFormItem>
|
||||
)
|
||||
}),
|
||||
useFormInput($t('t_1_1745735764953'), 'email', {
|
||||
placeholder: $t('t_0_1747965909665'),
|
||||
}),
|
||||
// 条件显示CADirURL字段
|
||||
...(shouldShowCADirURL.value
|
||||
? [
|
||||
useFormInput($t('t_5_1750129253961'), 'CADirURL', {
|
||||
placeholder: $t('t_6_1750129255766'),
|
||||
useFormInput('CA名称', 'caName', {
|
||||
placeholder: '请输入CA提供商名称',
|
||||
}),
|
||||
useFormInput($t('ACME服务URL地址'), 'CADirURL', {
|
||||
placeholder: $t('请输入ACME服务URL地址'),
|
||||
}),
|
||||
]
|
||||
: []),
|
||||
@@ -828,12 +873,17 @@ export const useCAFormController = (props?: { isEdit?: boolean; editId?: string
|
||||
// 提交表单
|
||||
const submitForm = async (formData: any) => {
|
||||
try {
|
||||
const dataToSubmit = { ...formData }
|
||||
if (dataToSubmit.ca === 'custom') {
|
||||
dataToSubmit.ca = dataToSubmit.caName
|
||||
}
|
||||
delete dataToSubmit.caName // 删除临时字段
|
||||
if (props?.isEdit && props?.editId) {
|
||||
// 编辑模式
|
||||
await updateExistingEab({ ...formData, id: props.editId })
|
||||
await updateExistingEab({ ...dataToSubmit, id: props.editId })
|
||||
} else {
|
||||
// 新增模式
|
||||
await addNewEab(formData)
|
||||
await addNewEab(dataToSubmit)
|
||||
}
|
||||
return true
|
||||
} catch (error) {
|
||||
@@ -843,7 +893,7 @@ export const useCAFormController = (props?: { isEdit?: boolean; editId?: string
|
||||
}
|
||||
|
||||
// 表单实例
|
||||
const { component: CAForm } = useForm({
|
||||
const { component: CAForm, fetch } = useForm({
|
||||
config: formConfig,
|
||||
rules: getFormRules(),
|
||||
defaultValue: caFormData,
|
||||
@@ -853,7 +903,7 @@ export const useCAFormController = (props?: { isEdit?: boolean; editId?: string
|
||||
// 确认提交表单
|
||||
confirm(async (close) => {
|
||||
try {
|
||||
await submitForm(caFormData.value)
|
||||
await fetch()
|
||||
close()
|
||||
} catch (error) {
|
||||
handleError(error)
|
||||
|
||||
@@ -13,12 +13,10 @@ import EmptyState from '@components/TableEmptyState'
|
||||
export default defineComponent({
|
||||
name: 'CertManage',
|
||||
setup() {
|
||||
const { TableComponent, PageComponent, fetch, data, param, openUploadModal, getRowClassName } = useController()
|
||||
const { TableComponent, PageComponent, SearchComponent, openUploadModal, getRowClassName } = useController()
|
||||
|
||||
const cssVar = useThemeCssVar(['contentPadding', 'borderColor', 'headerHeight', 'iconColorHover'])
|
||||
// 挂载时请求数据
|
||||
onMounted(() => fetch())
|
||||
const { theme, themeOverrides } = useTheme()
|
||||
console.log(theme.value, themeOverrides.value)
|
||||
|
||||
return () => (
|
||||
<div class="h-full flex flex-col" style={cssVar.value}>
|
||||
<div class="mx-auto max-w-[1600px] w-full p-6">
|
||||
@@ -29,26 +27,7 @@ export default defineComponent({
|
||||
{$t('t_13_1745227838275')}
|
||||
</NButton>
|
||||
),
|
||||
headerRight: () => (
|
||||
<NInput
|
||||
v-model:value={param.value.search}
|
||||
onKeydown={(e: KeyboardEvent) => {
|
||||
if (e.key === 'Enter') fetch()
|
||||
}}
|
||||
onClear={() => useThrottleFn(fetch, 100)}
|
||||
placeholder={$t('t_14_1745227840904')}
|
||||
clearable
|
||||
size="large"
|
||||
class="min-w-[300px]"
|
||||
v-slots={{
|
||||
suffix: () => (
|
||||
<div class="flex items-center" onClick={fetch}>
|
||||
<Search class="text-[var(--text-color-3)] w-[1.6rem] cursor-pointer font-bold" />
|
||||
</div>
|
||||
),
|
||||
}}
|
||||
></NInput>
|
||||
),
|
||||
headerRight: () => <SearchComponent placeholder={$t('t_14_1745227840904')} />,
|
||||
content: () => (
|
||||
<div class="rounded-lg">
|
||||
<TableComponent
|
||||
@@ -62,15 +41,7 @@ export default defineComponent({
|
||||
),
|
||||
footerRight: () => (
|
||||
<div class="mt-4 flex justify-end">
|
||||
<PageComponent
|
||||
v-slots={{
|
||||
prefix: () => (
|
||||
<span>
|
||||
{$t('t_15_1745227839354')} {data.value.total} {$t('t_16_1745227838930')}
|
||||
</span>
|
||||
),
|
||||
}}
|
||||
/>
|
||||
<PageComponent />
|
||||
</div>
|
||||
),
|
||||
}}
|
||||
|
||||
@@ -8,6 +8,7 @@ import {
|
||||
useForm,
|
||||
useLoadingMask,
|
||||
useMessage,
|
||||
useSearch,
|
||||
} from '@baota/naive-ui/hooks'
|
||||
import { useError } from '@baota/hooks/error'
|
||||
import { $t } from '@locales/index'
|
||||
@@ -135,6 +136,14 @@ export const useController = () => {
|
||||
storage: 'certManagePageSize',
|
||||
})
|
||||
|
||||
// 搜索实例
|
||||
const { SearchComponent } = useSearch({
|
||||
onSearch: (value) => {
|
||||
param.value.search = value
|
||||
fetch()
|
||||
},
|
||||
})
|
||||
|
||||
/**
|
||||
* @description 打开上传证书弹窗
|
||||
*/
|
||||
@@ -189,14 +198,14 @@ export const useController = () => {
|
||||
})
|
||||
}
|
||||
|
||||
onMounted(() => fetch())
|
||||
|
||||
return {
|
||||
loading,
|
||||
fetch,
|
||||
TableComponent,
|
||||
PageComponent,
|
||||
SearchComponent,
|
||||
getRowClassName,
|
||||
param,
|
||||
data,
|
||||
openUploadModal,
|
||||
openViewModal,
|
||||
}
|
||||
|
||||
@@ -18,7 +18,8 @@ export default defineComponent({
|
||||
name: 'MonitorManage',
|
||||
setup() {
|
||||
// 使用控制器获取数据和方法
|
||||
const { TableComponent, PageComponent, param, fetch, data, openAddForm, isDetectionAddMonitor } = useController()
|
||||
const { TableComponent, PageComponent, SearchComponent, fetch, openAddForm, isDetectionAddMonitor } =
|
||||
useController()
|
||||
|
||||
// 获取主题CSS变量
|
||||
const cssVar = useThemeCssVar(['contentPadding', 'borderColor', 'headerHeight', 'iconColorHover'])
|
||||
@@ -44,26 +45,7 @@ export default defineComponent({
|
||||
</NButton>
|
||||
),
|
||||
// 头部右侧区域 - 搜索框
|
||||
headerRight: () => (
|
||||
<NInput
|
||||
v-model:value={param.value.search}
|
||||
onKeydown={(e: KeyboardEvent) => {
|
||||
if (e.key === 'Enter') fetch()
|
||||
}}
|
||||
onClear={() => fetch()}
|
||||
placeholder={$t('t_12_1745289356974')}
|
||||
clearable
|
||||
size="large"
|
||||
class="min-w-[300px]"
|
||||
v-slots={{
|
||||
suffix: () => (
|
||||
<div class="flex items-center" onClick={fetch}>
|
||||
<Search class="text-[var(--text-color-3)] w-[1.6rem] cursor-pointer font-bold" />
|
||||
</div>
|
||||
),
|
||||
}}
|
||||
></NInput>
|
||||
),
|
||||
headerRight: () => <SearchComponent placeholder={$t('t_12_1745289356974')} />,
|
||||
// 内容区域 - 监控表格
|
||||
content: () => (
|
||||
<div class="rounded-lg">
|
||||
@@ -78,15 +60,7 @@ export default defineComponent({
|
||||
// 底部右侧区域 - 分页组件
|
||||
footerRight: () => (
|
||||
<div class="mt-4 flex justify-end">
|
||||
<PageComponent
|
||||
v-slots={{
|
||||
prefix: () => (
|
||||
<span>
|
||||
{$t('t_15_1745227839354')} {data.value.total} {$t('t_16_1745227838930')}
|
||||
</span>
|
||||
),
|
||||
}}
|
||||
/>
|
||||
<PageComponent />
|
||||
</div>
|
||||
),
|
||||
}}
|
||||
|
||||
@@ -11,6 +11,7 @@ import {
|
||||
useForm,
|
||||
useFormHooks,
|
||||
useLoadingMask,
|
||||
useSearch,
|
||||
} from '@baota/naive-ui/hooks'
|
||||
import { useError } from '@baota/hooks/error'
|
||||
import { isDomain, isPort, isIp } from '@baota/utils/business'
|
||||
@@ -38,9 +39,10 @@ interface MonitorControllerExposes {
|
||||
// 表格相关
|
||||
TableComponent: ReturnType<typeof useTable>['TableComponent']
|
||||
PageComponent: ReturnType<typeof useTable>['PageComponent']
|
||||
SearchComponent: ReturnType<typeof useSearch>['SearchComponent']
|
||||
loading: Ref<boolean>
|
||||
param: Ref<SiteMonitorListParams>
|
||||
data: Ref<{ list: SiteMonitorItem[]; total: number }>
|
||||
// param: Ref<SiteMonitorListParams>
|
||||
// data: Ref<{ list: SiteMonitorItem[]; total: number }>
|
||||
fetch: () => Promise<void>
|
||||
|
||||
// 表单和操作相关
|
||||
@@ -144,6 +146,24 @@ export const useController = (): MonitorControllerExposes => {
|
||||
width: 150,
|
||||
render: (row: SiteMonitorItem) => row.end_time + '(' + row.end_day + ')',
|
||||
},
|
||||
{
|
||||
title: $t('上次异常时间'),
|
||||
key: 'except_end_time',
|
||||
width: 150,
|
||||
render: (row: SiteMonitorItem) => row.except_end_time || '-',
|
||||
},
|
||||
{
|
||||
title: $t('上次检查时间'),
|
||||
key: 'last_time',
|
||||
width: 150,
|
||||
render: (row: SiteMonitorItem) => row.last_time || '-',
|
||||
},
|
||||
{
|
||||
title: $t('更新时间'),
|
||||
key: 'update_time',
|
||||
width: 150,
|
||||
render: (row: SiteMonitorItem) => row.update_time || '-',
|
||||
},
|
||||
{
|
||||
title: $t('t_18_1745289354598'),
|
||||
key: 'report_type',
|
||||
@@ -160,12 +180,6 @@ export const useController = (): MonitorControllerExposes => {
|
||||
return <NSwitch value={row.active === 1} onUpdateValue={() => toggleStatus(row)} />
|
||||
},
|
||||
},
|
||||
{
|
||||
title: $t('t_19_1745289354676'),
|
||||
key: 'update_time',
|
||||
width: 150,
|
||||
render: (row: SiteMonitorItem) => row.update_time || '-',
|
||||
},
|
||||
{
|
||||
title: $t('t_7_1745215914189'),
|
||||
key: 'create_time',
|
||||
@@ -196,10 +210,7 @@ export const useController = (): MonitorControllerExposes => {
|
||||
* 表格实例
|
||||
* @description 创建表格实例并管理相关状态
|
||||
*/
|
||||
const { TableComponent, PageComponent, loading, param, data, total, fetch } = useTable<
|
||||
SiteMonitorItem,
|
||||
SiteMonitorListParams
|
||||
>({
|
||||
const { TableComponent, PageComponent, loading, param, fetch } = useTable<SiteMonitorItem, SiteMonitorListParams>({
|
||||
config: createColumns(),
|
||||
request: fetchMonitorList,
|
||||
defaultValue: { p: 1, limit: 10, search: '' },
|
||||
@@ -208,15 +219,13 @@ export const useController = (): MonitorControllerExposes => {
|
||||
storage: 'monitorPageSize',
|
||||
})
|
||||
|
||||
// /**
|
||||
// * 分页实例
|
||||
// * @description 创建表格分页组件
|
||||
// */
|
||||
// const { component: MonitorTablePage } = useTablePage({
|
||||
// param,
|
||||
// total,
|
||||
// ,
|
||||
// })
|
||||
// 搜索实例
|
||||
const { SearchComponent } = useSearch({
|
||||
onSearch: (value) => {
|
||||
param.value.search = value
|
||||
fetch()
|
||||
},
|
||||
})
|
||||
|
||||
/**
|
||||
* 打开添加监控弹窗
|
||||
@@ -297,9 +306,8 @@ export const useController = (): MonitorControllerExposes => {
|
||||
fetch,
|
||||
TableComponent,
|
||||
PageComponent,
|
||||
SearchComponent,
|
||||
isDetectionAddMonitor,
|
||||
param,
|
||||
data,
|
||||
openAddForm,
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user