mirror of
				https://github.com/continew-org/continew-admin-ui.git
				synced 2025-10-31 22:57:15 +08:00 
			
		
		
		
	refactor: 优化登录验证码开关代码
This commit is contained in:
		| @@ -45,7 +45,6 @@ export interface RouteItem { | |||||||
| export interface AccountLoginReq { | export interface AccountLoginReq { | ||||||
|   username: string |   username: string | ||||||
|   password: string |   password: string | ||||||
|   unCaptcha: boolean |  | ||||||
|   captcha: string |   captcha: string | ||||||
|   uuid: string |   uuid: string | ||||||
| } | } | ||||||
|   | |||||||
| @@ -5,11 +5,6 @@ export type * from './type' | |||||||
|  |  | ||||||
| const BASE_URL = '/captcha' | const BASE_URL = '/captcha' | ||||||
|  |  | ||||||
| /** @desc 获取图片验证码 */ |  | ||||||
| export function getCaptchaConfig() { |  | ||||||
|   return http.get<boolean>(`${BASE_URL}/config`) |  | ||||||
| } |  | ||||||
|  |  | ||||||
| /** @desc 获取图片验证码 */ | /** @desc 获取图片验证码 */ | ||||||
| export function getImageCaptcha() { | export function getImageCaptcha() { | ||||||
|   return http.get<T.ImageCaptchaResp>(`${BASE_URL}/image`) |   return http.get<T.ImageCaptchaResp>(`${BASE_URL}/image`) | ||||||
|   | |||||||
| @@ -3,6 +3,7 @@ export interface ImageCaptchaResp { | |||||||
|   uuid: string |   uuid: string | ||||||
|   img: string |   img: string | ||||||
|   expireTime: number |   expireTime: number | ||||||
|  |   isEnabled: boolean | ||||||
| } | } | ||||||
|  |  | ||||||
| /** 仪表盘公告类型 */ | /** 仪表盘公告类型 */ | ||||||
|   | |||||||
| @@ -293,17 +293,6 @@ export interface SiteConfig { | |||||||
|   SITE_BEIAN: OptionResp |   SITE_BEIAN: OptionResp | ||||||
| } | } | ||||||
|  |  | ||||||
| /** 邮箱配置类型 */ |  | ||||||
| export interface MailConfig { |  | ||||||
|   MAIL_PROTOCOL: OptionResp |  | ||||||
|   MAIL_HOST: OptionResp |  | ||||||
|   MAIL_PORT: OptionResp |  | ||||||
|   MAIL_USERNAME: OptionResp |  | ||||||
|   MAIL_PASSWORD: OptionResp |  | ||||||
|   MAIL_SSL_ENABLED: OptionResp |  | ||||||
|   MAIL_SSL_PORT: OptionResp |  | ||||||
| } |  | ||||||
|  |  | ||||||
| /** 安全配置类型 */ | /** 安全配置类型 */ | ||||||
| export interface SecurityConfig { | export interface SecurityConfig { | ||||||
|   PASSWORD_ERROR_LOCK_COUNT: OptionResp |   PASSWORD_ERROR_LOCK_COUNT: OptionResp | ||||||
| @@ -316,9 +305,20 @@ export interface SecurityConfig { | |||||||
|   PASSWORD_REQUIRE_SYMBOLS: OptionResp |   PASSWORD_REQUIRE_SYMBOLS: OptionResp | ||||||
| } | } | ||||||
|  |  | ||||||
| /** 安全配置类型 */ | /** 邮箱配置类型 */ | ||||||
| export interface CaptchaSetting { | export interface MailConfig { | ||||||
|   NEED_CAPTCHA: OptionResp |   MAIL_PROTOCOL: OptionResp | ||||||
|  |   MAIL_HOST: OptionResp | ||||||
|  |   MAIL_PORT: OptionResp | ||||||
|  |   MAIL_USERNAME: OptionResp | ||||||
|  |   MAIL_PASSWORD: OptionResp | ||||||
|  |   MAIL_SSL_ENABLED: OptionResp | ||||||
|  |   MAIL_SSL_PORT: OptionResp | ||||||
|  | } | ||||||
|  |  | ||||||
|  | /** 登录配置类型 */ | ||||||
|  | export interface LoginConfig { | ||||||
|  |   LOGIN_CAPTCHA_ENABLED: OptionResp | ||||||
| } | } | ||||||
|  |  | ||||||
| /** 绑定三方账号信息 */ | /** 绑定三方账号信息 */ | ||||||
|   | |||||||
| @@ -1,18 +1,23 @@ | |||||||
| <template> | <template> | ||||||
|   <a-form |   <a-form | ||||||
|       ref="formRef" :model="form" :rules="rules" :label-col-style="{ display: 'none' }" |     ref="formRef" | ||||||
|       :wrapper-col-style="{ flex: 1 }" size="large" @submit="handleLogin" |     :model="form" | ||||||
|  |     :rules="rules" | ||||||
|  |     :label-col-style="{ display: 'none' }" | ||||||
|  |     :wrapper-col-style="{ flex: 1 }" | ||||||
|  |     size="large" | ||||||
|  |     @submit="handleLogin" | ||||||
|   > |   > | ||||||
|     <a-form-item field="username" hide-label> |     <a-form-item field="username" hide-label> | ||||||
|       <a-input v-model="form.username" placeholder="请输入用户名" allow-clear/> |       <a-input v-model="form.username" placeholder="请输入用户名" allow-clear /> | ||||||
|     </a-form-item> |     </a-form-item> | ||||||
|     <a-form-item field="password" hide-label> |     <a-form-item field="password" hide-label> | ||||||
|       <a-input-password v-model="form.password" placeholder="请输入密码"/> |       <a-input-password v-model="form.password" placeholder="请输入密码" /> | ||||||
|     </a-form-item> |     </a-form-item> | ||||||
|     <a-form-item field="captcha" hide-label v-if="unCaptcha"> |     <a-form-item v-if="isCaptchaEnabled" field="captcha" hide-label> | ||||||
|       <a-input v-model="form.captcha" placeholder="请输入验证码" :max-length="4" allow-clear style="flex: 1 1"/> |       <a-input v-model="form.captcha" placeholder="请输入验证码" :max-length="4" allow-clear style="flex: 1 1" /> | ||||||
|       <div class="captcha-container" @click="getCaptcha"> |       <div class="captcha-container" @click="getCaptcha"> | ||||||
|         <img :src="captchaImgBase64" alt="验证码" class="captcha"/> |         <img :src="captchaImgBase64" alt="验证码" class="captcha" /> | ||||||
|         <div v-if="form.expired" class="overlay"> |         <div v-if="form.expired" class="overlay"> | ||||||
|           <p>已过期,请刷新</p> |           <p>已过期,请刷新</p> | ||||||
|         </div> |         </div> | ||||||
| @@ -33,11 +38,11 @@ | |||||||
| </template> | </template> | ||||||
|  |  | ||||||
| <script setup lang="ts"> | <script setup lang="ts"> | ||||||
| import {type FormInstance, Message} from '@arco-design/web-vue' | import { type FormInstance, Message } from '@arco-design/web-vue' | ||||||
| import {useStorage} from '@vueuse/core' | import { useStorage } from '@vueuse/core' | ||||||
| import {getCaptchaConfig, getImageCaptcha} from '@/apis/common' | import { getImageCaptcha } from '@/apis/common' | ||||||
| import {useTabsStore, useUserStore} from '@/stores' | import { useTabsStore, useUserStore } from '@/stores' | ||||||
| import {encryptByRsa} from '@/utils/encrypt' | import { encryptByRsa } from '@/utils/encrypt' | ||||||
|  |  | ||||||
| const loginConfig = useStorage('login-config', { | const loginConfig = useStorage('login-config', { | ||||||
|   rememberMe: true, |   rememberMe: true, | ||||||
| @@ -46,8 +51,8 @@ const loginConfig = useStorage('login-config', { | |||||||
|   // username: debug ? 'admin' : '', // 演示默认值 |   // username: debug ? 'admin' : '', // 演示默认值 | ||||||
|   // password: debug ? 'admin123' : '', // 演示默认值 |   // password: debug ? 'admin123' : '', // 演示默认值 | ||||||
| }) | }) | ||||||
| // 是否开启验证码 | // 是否启用验证码 | ||||||
| const unCaptcha = ref(true) | const isCaptchaEnabled = ref(true) | ||||||
| // 验证码图片 | // 验证码图片 | ||||||
| const captchaImgBase64 = ref() | const captchaImgBase64 = ref() | ||||||
|  |  | ||||||
| @@ -55,15 +60,14 @@ const formRef = ref<FormInstance>() | |||||||
| const form = reactive({ | const form = reactive({ | ||||||
|   username: loginConfig.value.username, |   username: loginConfig.value.username, | ||||||
|   password: loginConfig.value.password, |   password: loginConfig.value.password, | ||||||
|   unCaptcha: unCaptcha.value, |  | ||||||
|   captcha: '', |   captcha: '', | ||||||
|   uuid: '', |   uuid: '', | ||||||
|   expired: false, |   expired: false, | ||||||
| }) | }) | ||||||
| const rules: FormInstance['rules'] = { | const rules: FormInstance['rules'] = { | ||||||
|   username: [{required: true, message: '请输入用户名'}], |   username: [{ required: true, message: '请输入用户名' }], | ||||||
|   password: [{required: true, message: '请输入密码'}], |   password: [{ required: true, message: '请输入密码' }], | ||||||
|   captcha: [{required: unCaptcha.value, message: '请输入验证码'}], |   captcha: [{ required: isCaptchaEnabled.value, message: '请输入验证码' }], | ||||||
| } | } | ||||||
|  |  | ||||||
| // 验证码过期定时器 | // 验证码过期定时器 | ||||||
| @@ -91,25 +95,15 @@ onBeforeUnmount(() => { | |||||||
| // 获取验证码 | // 获取验证码 | ||||||
| const getCaptcha = () => { | const getCaptcha = () => { | ||||||
|   getImageCaptcha().then((res) => { |   getImageCaptcha().then((res) => { | ||||||
|     const {uuid, img, expireTime} = res.data |     const { uuid, img, expireTime, isEnabled } = res.data | ||||||
|     form.uuid = uuid |     isCaptchaEnabled.value = isEnabled | ||||||
|     captchaImgBase64.value = img |     captchaImgBase64.value = img | ||||||
|  |     form.uuid = uuid | ||||||
|     form.expired = false |     form.expired = false | ||||||
|     startTimer(expireTime) |     startTimer(expireTime) | ||||||
|   }) |   }) | ||||||
| } | } | ||||||
|  |  | ||||||
| const initCaptchaConfig = () => { |  | ||||||
|   getCaptchaConfig().then((res) => { |  | ||||||
|     const result = res.data |  | ||||||
|     if (result.NEED_CAPTCHA == 0) { |  | ||||||
|       unCaptcha.value = false |  | ||||||
|     } else { |  | ||||||
|       getCaptcha() |  | ||||||
|     } |  | ||||||
|   }) |  | ||||||
| } |  | ||||||
|  |  | ||||||
| const userStore = useUserStore() | const userStore = useUserStore() | ||||||
| const tabsStore = useTabsStore() | const tabsStore = useTabsStore() | ||||||
| const router = useRouter() | const router = useRouter() | ||||||
| @@ -123,19 +117,18 @@ const handleLogin = async () => { | |||||||
|     await userStore.accountLogin({ |     await userStore.accountLogin({ | ||||||
|       username: form.username, |       username: form.username, | ||||||
|       password: encryptByRsa(form.password) || '', |       password: encryptByRsa(form.password) || '', | ||||||
|       unCaptcha: form.unCaptcha, |  | ||||||
|       captcha: form.captcha, |       captcha: form.captcha, | ||||||
|       uuid: form.uuid, |       uuid: form.uuid, | ||||||
|     }) |     }) | ||||||
|     tabsStore.reset() |     tabsStore.reset() | ||||||
|     const {redirect, ...othersQuery} = router.currentRoute.value.query |     const { redirect, ...othersQuery } = router.currentRoute.value.query | ||||||
|     await router.push({ |     await router.push({ | ||||||
|       path: (redirect as string) || '/', |       path: (redirect as string) || '/', | ||||||
|       query: { |       query: { | ||||||
|         ...othersQuery, |         ...othersQuery, | ||||||
|       }, |       }, | ||||||
|     }) |     }) | ||||||
|     const {rememberMe} = loginConfig.value |     const { rememberMe } = loginConfig.value | ||||||
|     loginConfig.value.username = rememberMe ? form.username : '' |     loginConfig.value.username = rememberMe ? form.username : '' | ||||||
|     Message.success('欢迎使用') |     Message.success('欢迎使用') | ||||||
|   } catch (error) { |   } catch (error) { | ||||||
| @@ -147,7 +140,7 @@ const handleLogin = async () => { | |||||||
| } | } | ||||||
|  |  | ||||||
| onMounted(() => { | onMounted(() => { | ||||||
|   initCaptchaConfig() |   getCaptcha() | ||||||
| }) | }) | ||||||
| </script> | </script> | ||||||
|  |  | ||||||
|   | |||||||
| @@ -1,53 +1,44 @@ | |||||||
| <template> | <template> | ||||||
|   <a-spin :loading="loading"> |   <a-spin :loading="loading"> | ||||||
|     <a-form |     <a-form | ||||||
|         ref="formRef" |       ref="formRef" | ||||||
|         :model="form" |       :model="form" | ||||||
|         auto-label-width |       :rules="rules" | ||||||
|         label-align="left" |       auto-label-width | ||||||
|         :layout="width >= 500 ? 'horizontal' : 'vertical'" |       label-align="left" | ||||||
|         :disabled="!isUpdate" |       :layout="width >= 500 ? 'horizontal' : 'vertical'" | ||||||
|         scroll-to-first-error> |       :disabled="!isUpdate" | ||||||
|  |       scroll-to-first-error | ||||||
|  |     > | ||||||
|       <a-form-item |       <a-form-item | ||||||
|           field="NEED_CAPTCHA" |         field="LOGIN_CAPTCHA_ENABLED" | ||||||
|           :label="captchaSetting.NEED_CAPTCHA.name" |         :label="loginConfig.LOGIN_CAPTCHA_ENABLED.name" | ||||||
|       > |       > | ||||||
|         <a-switch v-model="form.NEED_CAPTCHA" type="round" :checked-value="1" :unchecked-value="0"> |         <a-switch | ||||||
|  |           v-model="form.LOGIN_CAPTCHA_ENABLED" | ||||||
|  |           type="round" | ||||||
|  |           :checked-value="1" | ||||||
|  |           :unchecked-value="0" | ||||||
|  |         > | ||||||
|           <template #checked>是</template> |           <template #checked>是</template> | ||||||
|           <template #unchecked>否</template> |           <template #unchecked>否</template> | ||||||
|         </a-switch> |         </a-switch> | ||||||
|       </a-form-item> |       </a-form-item> | ||||||
| 
 |  | ||||||
|       <a-space style="margin-bottom: 16px"> |       <a-space style="margin-bottom: 16px"> | ||||||
|         <a-button v-if="!isUpdate" v-permission="['system:config:update']" type="primary" @click="onUpdate"> |         <a-button v-if="!isUpdate" v-permission="['system:config:update']" type="primary" @click="onUpdate"> | ||||||
|           <template #icon> |           <template #icon><icon-edit /></template>修改 | ||||||
|             <icon-edit/> |  | ||||||
|           </template> |  | ||||||
|           修改 |  | ||||||
|         </a-button> |         </a-button> | ||||||
|         <a-button v-if="!isUpdate" v-permission="['system:config:reset']" @click="onResetValue"> |         <a-button v-if="!isUpdate" v-permission="['system:config:reset']" @click="onResetValue"> | ||||||
|           <template #icon> |           <template #icon><icon-undo /></template>恢复默认 | ||||||
|             <icon-undo/> |  | ||||||
|           </template> |  | ||||||
|           恢复默认 |  | ||||||
|         </a-button> |         </a-button> | ||||||
|         <a-button v-if="isUpdate" type="primary" @click="handleSave"> |         <a-button v-if="isUpdate" type="primary" @click="handleSave"> | ||||||
|           <template #icon> |           <template #icon><icon-save /></template>保存 | ||||||
|             <icon-save/> |  | ||||||
|           </template> |  | ||||||
|           保存 |  | ||||||
|         </a-button> |         </a-button> | ||||||
|         <a-button v-if="isUpdate" @click="reset"> |         <a-button v-if="isUpdate" @click="reset"> | ||||||
|           <template #icon> |           <template #icon><icon-refresh /></template>重置 | ||||||
|             <icon-refresh/> |  | ||||||
|           </template> |  | ||||||
|           重置 |  | ||||||
|         </a-button> |         </a-button> | ||||||
|         <a-button v-if="isUpdate" @click="handleCancel"> |         <a-button v-if="isUpdate" @click="handleCancel"> | ||||||
|           <template #icon> |           <template #icon><icon-undo /></template>取消 | ||||||
|             <icon-undo/> |  | ||||||
|           </template> |  | ||||||
|           取消 |  | ||||||
|         </a-button> |         </a-button> | ||||||
|       </a-space> |       </a-space> | ||||||
|     </a-form> |     </a-form> | ||||||
| @@ -55,27 +46,31 @@ | |||||||
| </template> | </template> | ||||||
| 
 | 
 | ||||||
| <script setup lang="ts"> | <script setup lang="ts"> | ||||||
| import {useWindowSize} from '@vueuse/core' | import { useWindowSize } from '@vueuse/core' | ||||||
| import {type FormInstance, Message, Modal} from '@arco-design/web-vue' | import { type FormInstance, Message, Modal } from '@arco-design/web-vue' | ||||||
| import {type CaptchaSetting, listOption, type OptionResp, resetOptionValue, updateOption} from '@/apis/system' | import { type LoginConfig, type OptionResp, listOption, resetOptionValue, updateOption } from '@/apis/system' | ||||||
| import {useResetReactive} from '@/hooks' | import { useResetReactive } from '@/hooks' | ||||||
| 
 | 
 | ||||||
| defineOptions({name: 'CaptchaSetting'}) | defineOptions({ name: 'LoginSetting' }) | ||||||
| const {width} = useWindowSize() | const { width } = useWindowSize() | ||||||
| 
 | 
 | ||||||
| const loading = ref<boolean>(false) | const loading = ref<boolean>(false) | ||||||
| const formRef = ref<FormInstance>() | const formRef = ref<FormInstance>() | ||||||
| const [form] = useResetReactive({ | const [form] = useResetReactive({ | ||||||
|   NEED_CAPTCHA: 1, |   LOGIN_CAPTCHA_ENABLED: 1, | ||||||
|  | }) | ||||||
|  | const rules: FormInstance['rules'] = { | ||||||
|  |   LOGIN_CAPTCHA_ENABLED: [{ required: true, message: '请选择' }], | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | const loginConfig = ref<LoginConfig>({ | ||||||
|  |   LOGIN_CAPTCHA_ENABLED: {}, | ||||||
| }) | }) | ||||||
| 
 | 
 | ||||||
| const captchaSetting = ref<CaptchaSetting>({ |  | ||||||
|   NEED_CAPTCHA: {}, |  | ||||||
| }) |  | ||||||
| // 重置 | // 重置 | ||||||
| const reset = () => { | const reset = () => { | ||||||
|   formRef.value?.resetFields() |   formRef.value?.resetFields() | ||||||
|   form.NEED_CAPTCHA = captchaSetting.value.NEED_CAPTCHA.value |   form.LOGIN_CAPTCHA_ENABLED = loginConfig.value.LOGIN_CAPTCHA_ENABLED.value || 0 | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| const isUpdate = ref(false) | const isUpdate = ref(false) | ||||||
| @@ -91,19 +86,21 @@ const handleCancel = () => { | |||||||
| } | } | ||||||
| 
 | 
 | ||||||
| const queryForm = { | const queryForm = { | ||||||
|   category: 'CAPTCHA', |   category: 'LOGIN', | ||||||
| } | } | ||||||
| // 查询列表数据 | // 查询列表数据 | ||||||
| const getDataList = async () => { | const getDataList = async () => { | ||||||
|   loading.value = true |   try { | ||||||
|   const {data} = await listOption(queryForm) |     loading.value = true | ||||||
|   captchaSetting.value = data.reduce((obj: CaptchaSetting, option: OptionResp) => { |     const { data } = await listOption(queryForm) | ||||||
|     obj[option.code] = {...option, value: Number.parseInt(option.value)} |     loginConfig.value = data.reduce((obj: LoginConfig, option: OptionResp) => { | ||||||
|     return obj |       obj[option.code] = { ...option, value: Number.parseInt(option.value) } | ||||||
|   }, {}) |       return obj | ||||||
| 
 |     }, {}) | ||||||
|   handleCancel() |     handleCancel() | ||||||
|   loading.value = false |   } finally { | ||||||
|  |     loading.value = false | ||||||
|  |   } | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| // 保存 | // 保存 | ||||||
| @@ -111,9 +108,9 @@ const handleSave = async () => { | |||||||
|   const isInvalid = await formRef.value?.validate() |   const isInvalid = await formRef.value?.validate() | ||||||
|   if (isInvalid) return false |   if (isInvalid) return false | ||||||
|   await updateOption( |   await updateOption( | ||||||
|       Object.entries(form).map(([key, value]) => { |     Object.entries(form).map(([key, value]) => { | ||||||
|         return {id: captchaSetting.value[key].id, code: key, value} |       return { id: loginConfig.value[key].id, code: key, value } | ||||||
|       }), |     }), | ||||||
|   ) |   ) | ||||||
|   await getDataList() |   await getDataList() | ||||||
|   Message.success('保存成功') |   Message.success('保存成功') | ||||||
| @@ -128,7 +125,7 @@ const handleResetValue = async () => { | |||||||
| const onResetValue = () => { | const onResetValue = () => { | ||||||
|   Modal.warning({ |   Modal.warning({ | ||||||
|     title: '警告', |     title: '警告', | ||||||
|     content: '确认恢复安全配置为默认值吗?', |     content: '确认恢复登录配置为默认值吗?', | ||||||
|     hideCancel: false, |     hideCancel: false, | ||||||
|     maskClosable: false, |     maskClosable: false, | ||||||
|     onOk: handleResetValue, |     onOk: handleResetValue, | ||||||
| @@ -7,7 +7,8 @@ | |||||||
|       auto-label-width |       auto-label-width | ||||||
|       label-align="left" |       label-align="left" | ||||||
|       :layout="width >= 500 ? 'horizontal' : 'vertical'" |       :layout="width >= 500 ? 'horizontal' : 'vertical'" | ||||||
|       :disabled="!isUpdate" scroll-to-first-error |       :disabled="!isUpdate" | ||||||
|  |       scroll-to-first-error | ||||||
|     > |     > | ||||||
|       <a-form-item field="MAIL_PROTOCOL" :label="mailConfig.MAIL_PROTOCOL.name" hide-asterisk> |       <a-form-item field="MAIL_PROTOCOL" :label="mailConfig.MAIL_PROTOCOL.name" hide-asterisk> | ||||||
|         <a-select v-model.trim="form.MAIL_PROTOCOL"> |         <a-select v-model.trim="form.MAIL_PROTOCOL"> | ||||||
| @@ -27,10 +28,15 @@ | |||||||
|         <a-input-password v-model.trim="form.MAIL_PASSWORD" class="input-width" /> |         <a-input-password v-model.trim="form.MAIL_PASSWORD" class="input-width" /> | ||||||
|       </a-form-item> |       </a-form-item> | ||||||
|       <a-form-item field="MAIL_SSL_ENABLED" :label="mailConfig.MAIL_SSL_ENABLED?.name" hide-asterisk> |       <a-form-item field="MAIL_SSL_ENABLED" :label="mailConfig.MAIL_SSL_ENABLED?.name" hide-asterisk> | ||||||
|         <a-radio-group v-model:model-value="form.MAIL_SSL_ENABLED"> |         <a-switch | ||||||
|           <a-radio value="1">启用</a-radio> |           v-model="form.MAIL_SSL_ENABLED" | ||||||
|           <a-radio value="0">禁用</a-radio> |           type="round" | ||||||
|         </a-radio-group> |           :checked-value="1" | ||||||
|  |           :unchecked-value="0" | ||||||
|  |         > | ||||||
|  |           <template #checked>启用</template> | ||||||
|  |           <template #unchecked>禁用</template> | ||||||
|  |         </a-switch> | ||||||
|       </a-form-item> |       </a-form-item> | ||||||
|       <a-form-item |       <a-form-item | ||||||
|         v-if="form.MAIL_SSL_ENABLED === '1'" field="MAIL_SSL_PORT" :label="mailConfig.MAIL_SSL_PORT.name" |         v-if="form.MAIL_SSL_ENABLED === '1'" field="MAIL_SSL_PORT" :label="mailConfig.MAIL_SSL_PORT.name" | ||||||
|   | |||||||
| @@ -10,14 +10,14 @@ | |||||||
|         <template #title><icon-settings /> 基础配置</template> |         <template #title><icon-settings /> 基础配置</template> | ||||||
|       </a-tab-pane> |       </a-tab-pane> | ||||||
|       <a-tab-pane key="2"> |       <a-tab-pane key="2"> | ||||||
|         <template #title><icon-email /> 邮件配置</template> |  | ||||||
|       </a-tab-pane> |  | ||||||
|       <a-tab-pane key="3"> |  | ||||||
|         <template #title><icon-safe /> 安全配置</template> |         <template #title><icon-safe /> 安全配置</template> | ||||||
|       </a-tab-pane> |       </a-tab-pane> | ||||||
|  |       <a-tab-pane key="3"> | ||||||
|  |         <template #title><icon-email /> 邮件配置</template> | ||||||
|  |       </a-tab-pane> | ||||||
|       <a-tab-pane key="4"> |       <a-tab-pane key="4"> | ||||||
|       <template #title><icon-safe /> 登录配置</template> |         <template #title><icon-lock /> 登录配置</template> | ||||||
|     </a-tab-pane> |       </a-tab-pane> | ||||||
|     </a-tabs> |     </a-tabs> | ||||||
|     <keep-alive> |     <keep-alive> | ||||||
|       <component :is="PanMap[activeKey]" /> |       <component :is="PanMap[activeKey]" /> | ||||||
| @@ -28,16 +28,16 @@ | |||||||
| <script setup lang="ts"> | <script setup lang="ts"> | ||||||
| import { useRoute, useRouter } from 'vue-router' | import { useRoute, useRouter } from 'vue-router' | ||||||
| import BasicSetting from './components/BasicSetting.vue' | import BasicSetting from './components/BasicSetting.vue' | ||||||
| import MailSetting from './components/MailSetting.vue' |  | ||||||
| import SecuritySetting from './components/SecuritySetting.vue' | import SecuritySetting from './components/SecuritySetting.vue' | ||||||
| import LoginSetting from './components/CaptchaSetting.vue' | import MailSetting from './components/MailSetting.vue' | ||||||
|  | import LoginSetting from './components/LoginSetting.vue' | ||||||
|  |  | ||||||
| defineOptions({ name: 'SystemConfig' }) | defineOptions({ name: 'SystemConfig' }) | ||||||
|  |  | ||||||
| const PanMap: Record<string, Component> = { | const PanMap: Record<string, Component> = { | ||||||
|   1: BasicSetting, |   1: BasicSetting, | ||||||
|   2: MailSetting, |   2: SecuritySetting, | ||||||
|   3: SecuritySetting, |   3: MailSetting, | ||||||
|   4: LoginSetting, |   4: LoginSetting, | ||||||
| } | } | ||||||
|  |  | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user