mirror of
https://gitee.com/mirrors/AllinSSL.git
synced 2026-03-09 16:21:10 +08:00
【调整】更新API表单输入,新增密码类型和显示密码功能
【调整】登录页表单校验调整 【调整】新增阿里云dcdn部署类型
This commit is contained in:
@@ -618,6 +618,8 @@ export const useApiFormController = (props: ApiFormControllerProps): ApiFormCont
|
||||
]),
|
||||
(param.value.config as SshAccessConfig)?.mode === 'password'
|
||||
? useFormInput($t('t_48_1745289355714'), 'config.password', {
|
||||
type: 'password',
|
||||
showPasswordOn: 'click',
|
||||
allowInput: noSideSpace,
|
||||
})
|
||||
: useFormTextarea($t('t_1_1746667588689'), 'config.key', {
|
||||
@@ -655,6 +657,8 @@ export const useApiFormController = (props: ApiFormControllerProps): ApiFormCont
|
||||
allowInput: noSideSpace,
|
||||
}),
|
||||
useFormInput($t('t_55_1745289355715'), 'config.api_key', {
|
||||
type: 'password',
|
||||
showPasswordOn: 'click',
|
||||
allowInput: noSideSpace,
|
||||
}),
|
||||
useFormSwitch(
|
||||
@@ -676,6 +680,8 @@ export const useApiFormController = (props: ApiFormControllerProps): ApiFormCont
|
||||
param.value.type === 'safeline' ? $t('t_1_1747617105179') : $t('t_55_1745289355715'),
|
||||
param.value.type === 'safeline' ? 'config.api_token' : 'config.api_key',
|
||||
{
|
||||
type: 'password',
|
||||
showPasswordOn: 'click',
|
||||
allowInput: noSideSpace,
|
||||
},
|
||||
),
|
||||
@@ -690,13 +696,21 @@ export const useApiFormController = (props: ApiFormControllerProps): ApiFormCont
|
||||
case 'aliyun':
|
||||
items.push(
|
||||
useFormInput('AccessKeyId', 'config.access_key_id', { allowInput: noSideSpace }),
|
||||
useFormInput('AccessKeySecret', 'config.access_key_secret', { allowInput: noSideSpace }),
|
||||
useFormInput('AccessKeySecret', 'config.access_key_secret', {
|
||||
type: 'password',
|
||||
showPasswordOn: 'click',
|
||||
allowInput: noSideSpace,
|
||||
}),
|
||||
)
|
||||
break
|
||||
case 'tencentcloud':
|
||||
items.push(
|
||||
useFormInput('SecretId', 'config.secret_id', { allowInput: noSideSpace }),
|
||||
useFormInput('SecretKey', 'config.secret_key', { allowInput: noSideSpace }),
|
||||
useFormInput('SecretKey', 'config.secret_key', {
|
||||
type: 'password',
|
||||
showPasswordOn: 'click',
|
||||
allowInput: noSideSpace,
|
||||
}),
|
||||
)
|
||||
break
|
||||
case 'huaweicloud':
|
||||
@@ -705,13 +719,21 @@ export const useApiFormController = (props: ApiFormControllerProps): ApiFormCont
|
||||
case 'doge':
|
||||
items.push(
|
||||
useFormInput('AccessKey', 'config.access_key', { allowInput: noSideSpace }),
|
||||
useFormInput('SecretKey', 'config.secret_key', { allowInput: noSideSpace }),
|
||||
useFormInput('SecretKey', 'config.secret_key', {
|
||||
type: 'password',
|
||||
showPasswordOn: 'click',
|
||||
allowInput: noSideSpace,
|
||||
}),
|
||||
)
|
||||
break
|
||||
case 'cloudflare':
|
||||
items.push(
|
||||
useFormInput('邮箱', 'config.email', { allowInput: noSideSpace }, { showRequireMark: false }),
|
||||
useFormInput('APIKey', 'config.api_key', { allowInput: noSideSpace }),
|
||||
useFormInput('APIKey', 'config.api_key', {
|
||||
type: 'password',
|
||||
showPasswordOn: 'click',
|
||||
allowInput: noSideSpace,
|
||||
}),
|
||||
useFormCustom(() => {
|
||||
return (
|
||||
<NAlert type="error" class="mt-[1.2rem] whitespace-nowrap" showIcon={false}>
|
||||
@@ -724,76 +746,144 @@ export const useApiFormController = (props: ApiFormControllerProps): ApiFormCont
|
||||
case 'westcn':
|
||||
items.push(
|
||||
useFormInput('Username', 'config.username', { allowInput: noSideSpace }),
|
||||
useFormInput('Password', 'config.password', { allowInput: noSideSpace }),
|
||||
useFormInput('Password', 'config.password', {
|
||||
type: 'password',
|
||||
showPasswordOn: 'click',
|
||||
allowInput: noSideSpace,
|
||||
}),
|
||||
)
|
||||
break
|
||||
case 'godaddy':
|
||||
items.push(
|
||||
useFormInput('API Key', 'config.api_key', { allowInput: noSideSpace }),
|
||||
useFormInput('API Secret', 'config.api_secret', { allowInput: noSideSpace }),
|
||||
useFormInput('API Key', 'config.api_key', {
|
||||
type: 'password',
|
||||
showPasswordOn: 'click',
|
||||
allowInput: noSideSpace,
|
||||
}),
|
||||
useFormInput('API Secret', 'config.api_secret', {
|
||||
type: 'password',
|
||||
showPasswordOn: 'click',
|
||||
allowInput: noSideSpace,
|
||||
}),
|
||||
)
|
||||
break
|
||||
case 'qiniu':
|
||||
items.push(
|
||||
useFormInput('AccessKey', 'config.access_key', { allowInput: noSideSpace }),
|
||||
useFormInput('AccessSecret', 'config.access_secret', { allowInput: noSideSpace }),
|
||||
useFormInput('AccessSecret', 'config.access_secret', {
|
||||
type: 'password',
|
||||
showPasswordOn: 'click',
|
||||
allowInput: noSideSpace,
|
||||
}),
|
||||
)
|
||||
break
|
||||
case 'namecheap':
|
||||
items.push(
|
||||
useFormInput('API User', 'config.api_user', { allowInput: noSideSpace }),
|
||||
useFormInput('API Key', 'config.api_key', { allowInput: noSideSpace }),
|
||||
useFormInput('API Key', 'config.api_key', {
|
||||
type: 'password',
|
||||
showPasswordOn: 'click',
|
||||
allowInput: noSideSpace,
|
||||
}),
|
||||
)
|
||||
break
|
||||
case 'ns1':
|
||||
items.push(useFormInput('API Key', 'config.api_key', { allowInput: noSideSpace }))
|
||||
items.push(
|
||||
useFormInput('API Key', 'config.api_key', {
|
||||
type: 'password',
|
||||
showPasswordOn: 'click',
|
||||
allowInput: noSideSpace,
|
||||
}),
|
||||
)
|
||||
break
|
||||
case 'cloudns':
|
||||
items.push(
|
||||
useFormInput('Auth ID', 'config.auth_id', { allowInput: noSideSpace }),
|
||||
useFormInput('Auth Password', 'config.auth_password', { allowInput: noSideSpace }),
|
||||
useFormInput('Auth Password', 'config.auth_password', {
|
||||
type: 'password',
|
||||
showPasswordOn: 'click',
|
||||
allowInput: noSideSpace,
|
||||
}),
|
||||
)
|
||||
break
|
||||
case 'aws':
|
||||
items.push(
|
||||
useFormInput('Access Key ID', 'config.access_key_id', { allowInput: noSideSpace }),
|
||||
useFormInput('Secret Access Key', 'config.secret_access_key', { allowInput: noSideSpace }),
|
||||
useFormInput('Secret Access Key', 'config.secret_access_key', {
|
||||
type: 'password',
|
||||
showPasswordOn: 'click',
|
||||
allowInput: noSideSpace,
|
||||
}),
|
||||
)
|
||||
break
|
||||
case 'azure':
|
||||
items.push(
|
||||
useFormInput('Tenant ID', 'config.tenant_id', { allowInput: noSideSpace }),
|
||||
useFormInput('Client ID', 'config.client_id', { allowInput: noSideSpace }),
|
||||
useFormInput('Client Secret', 'config.client_secret', { allowInput: noSideSpace }),
|
||||
useFormInput('Client Secret', 'config.client_secret', {
|
||||
type: 'password',
|
||||
showPasswordOn: 'click',
|
||||
allowInput: noSideSpace,
|
||||
}),
|
||||
useFormInput('Environment', 'config.environment', { allowInput: noSideSpace, placeholder: 'public' }),
|
||||
)
|
||||
break
|
||||
case 'namesilo':
|
||||
items.push(useFormInput('API Key', 'config.api_key', { allowInput: noSideSpace }))
|
||||
items.push(
|
||||
useFormInput('API Key', 'config.api_key', {
|
||||
type: 'password',
|
||||
showPasswordOn: 'click',
|
||||
allowInput: noSideSpace,
|
||||
}),
|
||||
)
|
||||
break
|
||||
case 'namedotcom':
|
||||
items.push(
|
||||
useFormInput('Username', 'config.username', { allowInput: noSideSpace }),
|
||||
useFormInput('API Token', 'config.api_token', { allowInput: noSideSpace }),
|
||||
useFormInput('API Token', 'config.api_token', {
|
||||
type: 'password',
|
||||
showPasswordOn: 'click',
|
||||
allowInput: noSideSpace,
|
||||
}),
|
||||
)
|
||||
break
|
||||
case 'bunny':
|
||||
items.push(useFormInput('API Key', 'config.api_key', { allowInput: noSideSpace }))
|
||||
items.push(
|
||||
useFormInput('API Key', 'config.api_key', {
|
||||
type: 'password',
|
||||
showPasswordOn: 'click',
|
||||
allowInput: noSideSpace,
|
||||
}),
|
||||
)
|
||||
break
|
||||
case 'gcore':
|
||||
items.push(useFormInput('API Token', 'config.api_token', { allowInput: noSideSpace }))
|
||||
items.push(
|
||||
useFormInput('API Token', 'config.api_token', {
|
||||
type: 'password',
|
||||
showPasswordOn: 'click',
|
||||
allowInput: noSideSpace,
|
||||
}),
|
||||
)
|
||||
break
|
||||
case 'jdcloud':
|
||||
items.push(
|
||||
useFormInput('Access Key ID', 'config.access_key_id', { allowInput: noSideSpace }),
|
||||
useFormInput('Secret Access Key', 'config.secret_access_key', { allowInput: noSideSpace }),
|
||||
useFormInput('Secret Access Key', 'config.secret_access_key', {
|
||||
type: 'password',
|
||||
showPasswordOn: 'click',
|
||||
allowInput: noSideSpace,
|
||||
}),
|
||||
)
|
||||
break
|
||||
case 'lecdn':
|
||||
items.push(
|
||||
useFormInput('URL', 'config.url', { allowInput: noSideSpace }),
|
||||
useFormInput('Username', 'config.username', { allowInput: noSideSpace }),
|
||||
useFormInput('Password', 'config.password', { allowInput: noSideSpace }),
|
||||
useFormInput('Password', 'config.password', {
|
||||
type: 'password',
|
||||
showPasswordOn: 'click',
|
||||
allowInput: noSideSpace,
|
||||
}),
|
||||
useFormSwitch(
|
||||
$t('t_3_1746667592270'),
|
||||
'config.ignore_ssl',
|
||||
@@ -804,8 +894,16 @@ export const useApiFormController = (props: ApiFormControllerProps): ApiFormCont
|
||||
break
|
||||
case 'constellix':
|
||||
items.push(
|
||||
useFormInput('API Key', 'config.api_key', { allowInput: noSideSpace }),
|
||||
useFormInput('Secret Key', 'config.secret_key', { allowInput: noSideSpace }),
|
||||
useFormInput('API Key', 'config.api_key', {
|
||||
type: 'password',
|
||||
showPasswordOn: 'click',
|
||||
allowInput: noSideSpace,
|
||||
}),
|
||||
useFormInput('Secret Key', 'config.secret_key', {
|
||||
type: 'password',
|
||||
showPasswordOn: 'click',
|
||||
allowInput: noSideSpace,
|
||||
}),
|
||||
)
|
||||
break
|
||||
case 'plugin':
|
||||
|
||||
@@ -205,6 +205,7 @@ export default defineComponent({
|
||||
case 'tencentcloud-waf':
|
||||
case 'tencentcloud-teo':
|
||||
case 'aliyun-cdn':
|
||||
case 'aliyun-dcdn':
|
||||
case 'baidu-cdn':
|
||||
case 'qiniu-cdn':
|
||||
case 'qiniu-oss':
|
||||
|
||||
@@ -12,6 +12,7 @@ import {
|
||||
} from '@baota/naive-ui/hooks'
|
||||
import { useError } from '@baota/hooks/error'
|
||||
import { $t } from '@locales/index'
|
||||
import { getDaysDiff } from '@baota/utils/date'
|
||||
|
||||
import { useStore } from './useStore'
|
||||
|
||||
@@ -22,6 +23,41 @@ const { useFormTextarea } = useFormHooks()
|
||||
const { fetchCertList, downloadExistingCert, deleteExistingCert, uploadNewCert, uploadForm, resetUploadForm } =
|
||||
useStore()
|
||||
const { confirm } = useModalHooks()
|
||||
/**
|
||||
* 计算证书剩余天数
|
||||
* @param cert 证书项
|
||||
* @returns 剩余天数,如果无法计算则返回 null
|
||||
*/
|
||||
const calculateRemainingDays = (cert: CertItem): number | null => {
|
||||
// 首先尝试使用后端提供的 end_day 字段
|
||||
const endDay = Number(cert.end_day)
|
||||
if (!isNaN(endDay) && endDay !== 0) {
|
||||
return endDay
|
||||
}
|
||||
|
||||
// 如果 end_day 无效,则根据 end_time 计算
|
||||
if (cert.end_time) {
|
||||
try {
|
||||
const endTime = new Date(cert.end_time)
|
||||
const currentTime = new Date()
|
||||
|
||||
// 检查日期是否有效
|
||||
if (isNaN(endTime.getTime())) {
|
||||
return null
|
||||
}
|
||||
|
||||
// 计算剩余天数
|
||||
const endDay = getDaysDiff(currentTime, endTime)
|
||||
return endDay
|
||||
} catch (error) {
|
||||
console.warn('计算证书剩余天数失败:', error)
|
||||
return null
|
||||
}
|
||||
}
|
||||
|
||||
return null
|
||||
}
|
||||
|
||||
/**
|
||||
* useController
|
||||
* @description 证书管理业务逻辑控制器
|
||||
@@ -60,13 +96,27 @@ export const useController = () => {
|
||||
key: 'end_day',
|
||||
width: 100,
|
||||
render: (row: CertItem) => {
|
||||
const endDay = Number(row.end_day)
|
||||
const endDay = calculateRemainingDays(row)
|
||||
|
||||
// 如果无法计算剩余天数,显示获取失败
|
||||
if (endDay === null) {
|
||||
return (
|
||||
<NTag type="error" size="small">
|
||||
获取失败
|
||||
</NTag>
|
||||
)
|
||||
}
|
||||
|
||||
// 根据剩余天数确定显示样式和文本
|
||||
const config = [
|
||||
[endDay <= 0, 'error', $t('t_0_1746001199409')],
|
||||
[endDay < 30, 'warning', $t('t_1_1745999036289', { days: row.end_day })],
|
||||
[endDay > 30, 'success', $t('t_0_1745999035681', { days: row.end_day })],
|
||||
[endDay < 30, 'warning', $t('t_1_1745999036289', { days: endDay })],
|
||||
[endDay >= 30, 'success', $t('t_0_1745999035681', { days: endDay })],
|
||||
] as [boolean, 'success' | 'error' | 'warning' | 'default' | 'info' | 'primary', string][]
|
||||
const [_, type, text] = config.find((item) => item[0]) ?? ['default', 'error', '获取失败']
|
||||
|
||||
const matchedConfig = config.find((item) => item[0])
|
||||
const [, type, text] = matchedConfig ?? ['default', 'error', '获取失败']
|
||||
|
||||
return (
|
||||
<NTag type={type} size="small">
|
||||
{text}
|
||||
@@ -116,7 +166,13 @@ export const useController = () => {
|
||||
* - 空字符串:其他情况。
|
||||
*/
|
||||
const getRowClassName = (row: CertItem): string => {
|
||||
const endDay = Number(row.end_day)
|
||||
const endDay = calculateRemainingDays(row)
|
||||
|
||||
// 如果无法计算剩余天数,不应用特殊样式
|
||||
if (endDay === null) {
|
||||
return ''
|
||||
}
|
||||
|
||||
if (endDay <= 0) {
|
||||
return 'bg-red-500/10' // Tailwind class for light red background
|
||||
}
|
||||
|
||||
@@ -15,7 +15,7 @@ import styles from './index.module.css'
|
||||
export default defineComponent({
|
||||
name: 'LoginView',
|
||||
setup() {
|
||||
const { loading, error, rememberMe, handleSubmit, handleKeyup, loginData, handleGetCode, codeImg, mustCode } =
|
||||
const { loading, error, rememberMe, handleSubmit, handleKeyup, loginData, handleGetCode, codeImg, mustCode, formRef } =
|
||||
useController()
|
||||
const { isDark } = useTheme()
|
||||
const cssVar = useThemeCssVar(['textColor2', 'actionColor', 'errorColor', 'primaryColor', 'primaryColorSuppl'])
|
||||
@@ -39,7 +39,7 @@ export default defineComponent({
|
||||
<div class={styles.rightSection}>
|
||||
<div class={styles.formContainer}>
|
||||
<h1 class={styles.title}>{$t('t_2_1744164839713')}</h1>
|
||||
<NForm onSubmit={handleSubmit} class={styles.formWrapper}>
|
||||
<NForm ref={formRef} model={loginData.value} onSubmit={handleSubmit} class={styles.formWrapper}>
|
||||
<div class={styles.formContent}>
|
||||
<div class={styles.formInputs}>
|
||||
<NFormItem
|
||||
@@ -84,7 +84,11 @@ export default defineComponent({
|
||||
<NFormItem
|
||||
show-label={false}
|
||||
path="code"
|
||||
rule={{ required: true, message: $t('t_25_1745289355721'), trigger: ['input', 'blur'] }}
|
||||
rule={{
|
||||
required: mustCode.value,
|
||||
message: $t('t_25_1745289355721'),
|
||||
trigger: ['input', 'blur']
|
||||
}}
|
||||
>
|
||||
<NInput
|
||||
onKeyup={handleKeyup}
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
// External Libraries
|
||||
import md5 from 'crypto-js/md5'
|
||||
import type { FormInst } from 'naive-ui'
|
||||
|
||||
// Type Imports
|
||||
import type { LoginParams } from '@/types/login'
|
||||
|
||||
// Absolute Internal Imports
|
||||
import { useError } from '@baota/hooks/error'
|
||||
import { $t } from '@locales/index'
|
||||
|
||||
// Relative Internal Imports
|
||||
import { useStore } from './useStore'
|
||||
@@ -51,6 +51,7 @@ const setRememberData = (username: string, password: string): void => {
|
||||
*/
|
||||
interface LoginControllerExposes extends ReturnType<typeof useStore> {
|
||||
// 继承自 useStore 的返回类型
|
||||
formRef: Ref<FormInst | null>
|
||||
handleSubmit: (event: Event) => Promise<void>
|
||||
handleKeyup: (event: KeyboardEvent) => void
|
||||
handleLogin: (params: LoginParams) => Promise<void> // 覆盖 store 中的 handleLogin
|
||||
@@ -69,25 +70,14 @@ export const useController = (): LoginControllerExposes => {
|
||||
// 从 store 中解构需要的状态和方法
|
||||
const { error, loginData, handleLogin: storeHandleLogin, rememberMe, checkMustCode, mustCode, handleGetCode } = store
|
||||
|
||||
// 表单引用
|
||||
const formRef = ref<FormInst | null>(null)
|
||||
|
||||
/**
|
||||
* @description 处理登录业务逻辑,包括表单验证和密码加密
|
||||
* @param params - 登录参数 (用户名、密码等)
|
||||
*/
|
||||
const handleLoginBusiness = async (params: LoginParams): Promise<void> => {
|
||||
// 表单验证
|
||||
if (!params.username.trim()) {
|
||||
error.value = $t('t_3_1744164839524') // 请输入用户名
|
||||
return
|
||||
}
|
||||
if (!params.password.trim()) {
|
||||
error.value = $t('t_4_1744164840458') // 请输入密码
|
||||
return
|
||||
}
|
||||
if (mustCode.value && !params.code?.trim()) {
|
||||
error.value = $t('t_25_1745289355721') // 请输入验证码
|
||||
return
|
||||
}
|
||||
|
||||
try {
|
||||
const encryptedPassword = encryptPassword(params.password)
|
||||
await storeHandleLogin({ ...params, password: encryptedPassword }) // 调用 store 中的登录方法
|
||||
@@ -117,7 +107,18 @@ export const useController = (): LoginControllerExposes => {
|
||||
*/
|
||||
const handleSubmit = async (event: Event): Promise<void> => {
|
||||
event.preventDefault()
|
||||
await handleLoginBusiness(loginData.value)
|
||||
|
||||
// 使用 NForm 的校验机制
|
||||
if (!formRef.value) return
|
||||
|
||||
try {
|
||||
await formRef.value.validate()
|
||||
// 校验通过,执行登录逻辑
|
||||
await handleLoginBusiness(loginData.value)
|
||||
} catch (validationErrors) {
|
||||
// 校验失败,NForm 会自动显示错误信息
|
||||
console.log('表单校验失败:', validationErrors)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -163,6 +164,7 @@ export const useController = (): LoginControllerExposes => {
|
||||
// ==================== 返回值 ====================
|
||||
return {
|
||||
...store, // 暴露 store 中的所有属性和方法
|
||||
formRef,
|
||||
handleSubmit,
|
||||
handleKeyup,
|
||||
handleLogin: handleLoginBusiness, // 控制器封装的登录逻辑
|
||||
|
||||
Reference in New Issue
Block a user