mirror of
				https://github.com/continew-org/continew-admin-ui.git
				synced 2025-10-31 00:57:11 +08:00 
			
		
		
		
	chore:优化系统配置加载与切换问题
This commit is contained in:
		| @@ -7,7 +7,7 @@ | |||||||
|         </slot> |         </slot> | ||||||
|       </a-space> |       </a-space> | ||||||
|     </a-row> |     </a-row> | ||||||
|     <a-tabs type="card-gutter" size="large" :active-key="activeKey" @change="change"> |     <a-tabs v-model:active-key="activeKey" type="card-gutter" size="large" @change="change"> | ||||||
|       <a-tab-pane key="1" title="登录日志" /> |       <a-tab-pane key="1" title="登录日志" /> | ||||||
|       <a-tab-pane key="2" title="操作日志" /> |       <a-tab-pane key="2" title="操作日志" /> | ||||||
|     </a-tabs> |     </a-tabs> | ||||||
|   | |||||||
| @@ -7,23 +7,13 @@ | |||||||
|           <template #extra> |           <template #extra> | ||||||
|             {{ siteFavicon?.description }} |             {{ siteFavicon?.description }} | ||||||
|             <br /> |             <br /> | ||||||
|             <a-upload |             <a-upload :file-list="faviconFile ? [faviconFile] : []" accept="image/*" :show-file-list="false" | ||||||
|               :file-list="faviconFile ? [faviconFile] : []" |               :custom-request="handleUploadFavicon" @change="handleChangeFavicon"> | ||||||
|               accept="image/*" |  | ||||||
|               :show-file-list="false" |  | ||||||
|               :custom-request="handleUploadFavicon" |  | ||||||
|               @change="handleChangeFavicon" |  | ||||||
|             > |  | ||||||
|               <template #upload-button> |               <template #upload-button> | ||||||
|                 <div |                 <div :class="`arco-upload-list-item${faviconFile && faviconFile.status === 'error' ? ' arco-upload-list-item-error' : '' | ||||||
|                   :class="`arco-upload-list-item${ |                   }`"> | ||||||
|                     faviconFile && faviconFile.status === 'error' ? ' arco-upload-list-item-error' : '' |                   <div v-if="faviconFile && faviconFile.url" | ||||||
|                   }`" |                     class="arco-upload-list-picture custom-upload-avatar favicon"> | ||||||
|                 > |  | ||||||
|                   <div |  | ||||||
|                     v-if="faviconFile && faviconFile.url" |  | ||||||
|                     class="arco-upload-list-picture custom-upload-avatar favicon" |  | ||||||
|                   > |  | ||||||
|                     <img :src="faviconFile.url" alt="favicon" /> |                     <img :src="faviconFile.url" alt="favicon" /> | ||||||
|                     <div v-if="isUpdate" class="arco-upload-list-picture-mask favicon"> |                     <div v-if="isUpdate" class="arco-upload-list-picture-mask favicon"> | ||||||
|                       <IconEdit /> |                       <IconEdit /> | ||||||
| @@ -46,19 +36,11 @@ | |||||||
|           <template #extra> |           <template #extra> | ||||||
|             {{ siteLogo?.description }} |             {{ siteLogo?.description }} | ||||||
|             <br /> |             <br /> | ||||||
|             <a-upload |             <a-upload :file-list="logoFile ? [logoFile] : []" accept="image/*" :show-file-list="false" | ||||||
|               :file-list="logoFile ? [logoFile] : []" |               :custom-request="handleUploadLogo" @change="handleChangeLogo"> | ||||||
|               accept="image/*" |  | ||||||
|               :show-file-list="false" |  | ||||||
|               :custom-request="handleUploadLogo" |  | ||||||
|               @change="handleChangeLogo" |  | ||||||
|             > |  | ||||||
|               <template #upload-button> |               <template #upload-button> | ||||||
|                 <div |                 <div :class="`arco-upload-list-item${logoFile && logoFile.status === 'error' ? ' arco-upload-list-item-error' : '' | ||||||
|                   :class="`arco-upload-list-item${ |                   }`"> | ||||||
|                     logoFile && logoFile.status === 'error' ? ' arco-upload-list-item-error' : '' |  | ||||||
|                   }`" |  | ||||||
|                 > |  | ||||||
|                   <div v-if="logoFile && logoFile.url" class="arco-upload-list-picture custom-upload-avatar logo"> |                   <div v-if="logoFile && logoFile.url" class="arco-upload-list-picture custom-upload-avatar logo"> | ||||||
|                     <img :src="logoFile.url" alt="Logo" /> |                     <img :src="logoFile.url" alt="Logo" /> | ||||||
|                     <div v-if="isUpdate" class="arco-upload-list-picture-mask logo"> |                     <div v-if="isUpdate" class="arco-upload-list-picture-mask logo"> | ||||||
| @@ -81,14 +63,9 @@ | |||||||
|           <a-input v-model.trim="form.SITE_TITLE" placeholder="请输入网站标题" :max-length="18" /> |           <a-input v-model.trim="form.SITE_TITLE" placeholder="请输入网站标题" :max-length="18" /> | ||||||
|         </a-form-item> |         </a-form-item> | ||||||
|         <a-form-item class="input-item" :label="siteCopyright?.name" field="SITE_COPYRIGHT" tooltip="支持HTML标签"> |         <a-form-item class="input-item" :label="siteCopyright?.name" field="SITE_COPYRIGHT" tooltip="支持HTML标签"> | ||||||
|           <a-textarea |           <a-textarea v-model.trim="form.SITE_COPYRIGHT" placeholder="请输入版权信息" :auto-size="{ | ||||||
|             v-model.trim="form.SITE_COPYRIGHT" |  | ||||||
|             placeholder="请输入版权信息" |  | ||||||
|             :auto-size="{ |  | ||||||
|             minRows: 3, |             minRows: 3, | ||||||
|             }" |           }" show-word-limit /> | ||||||
|             show-word-limit |  | ||||||
|           /> |  | ||||||
|         </a-form-item> |         </a-form-item> | ||||||
|         <div style="margin-top: 20px"> |         <div style="margin-top: 20px"> | ||||||
|           <a-space> |           <a-space> | ||||||
| @@ -135,6 +112,7 @@ import { type OptionResp, listOption, resetOptionValue, updateOption, uploadFile | |||||||
| import { useAppStore } from '@/stores' | import { useAppStore } from '@/stores' | ||||||
| import { useForm } from '@/hooks' | import { useForm } from '@/hooks' | ||||||
|  |  | ||||||
|  | defineOptions({ name: 'BasicSetting' }) | ||||||
| const formRef = ref<FormInstance>() | const formRef = ref<FormInstance>() | ||||||
| const rules: FormInstance['rules'] = { | const rules: FormInstance['rules'] = { | ||||||
|   SITE_TITLE: [{ required: true, message: '请输入系统标题' }], |   SITE_TITLE: [{ required: true, message: '请输入系统标题' }], | ||||||
| @@ -227,7 +205,7 @@ const onResetValue = () => { | |||||||
| // 上传 favicon | // 上传 favicon | ||||||
| const handleUploadFavicon = (options: RequestOption) => { | const handleUploadFavicon = (options: RequestOption) => { | ||||||
|   const controller = new AbortController() |   const controller = new AbortController() | ||||||
|   ;(async function requestWrap() { |     ; (async function requestWrap() { | ||||||
|       const { onProgress, onError, onSuccess, fileItem, name = 'file' } = options |       const { onProgress, onError, onSuccess, fileItem, name = 'file' } = options | ||||||
|       onProgress(20) |       onProgress(20) | ||||||
|       const formData = new FormData() |       const formData = new FormData() | ||||||
| @@ -257,7 +235,7 @@ const handleChangeFavicon = (_: any, currentFile: any) => { | |||||||
| // 上传 Logo | // 上传 Logo | ||||||
| const handleUploadLogo = (options: RequestOption) => { | const handleUploadLogo = (options: RequestOption) => { | ||||||
|   const controller = new AbortController() |   const controller = new AbortController() | ||||||
|   ;(async function requestWrap() { |     ; (async function requestWrap() { | ||||||
|       const { onProgress, onError, onSuccess, fileItem, name = 'file' } = options |       const { onProgress, onError, onSuccess, fileItem, name = 'file' } = options | ||||||
|       onProgress(20) |       onProgress(20) | ||||||
|       const formData = new FormData() |       const formData = new FormData() | ||||||
|   | |||||||
| @@ -3,7 +3,7 @@ | |||||||
| </template> | </template> | ||||||
|  |  | ||||||
| <script lang="ts" setup> | <script lang="ts" setup> | ||||||
|  | defineOptions({ name: 'MailSetting' }) | ||||||
| </script> | </script> | ||||||
|  |  | ||||||
| <style lang="scss" scoped> | <style lang="scss" scoped></style> | ||||||
| </style> |  | ||||||
|   | |||||||
| @@ -1,92 +1,62 @@ | |||||||
| <template> | <template> | ||||||
|   <a-form |   <a-form ref="formRef" :model="form" :rules="rules" size="small" :auto-label-width="true" label-align="left" | ||||||
|     ref="formRef" |     :layout="width >= 500 ? 'horizontal' : 'vertical'" :disabled="!isUpdate" scroll-to-first-error | ||||||
|     :model="form" |     style="margin-top: 10px"> | ||||||
|     :rules="rules" |  | ||||||
|     size="small" |  | ||||||
|     :auto-label-width="true" |  | ||||||
|     label-align="left" |  | ||||||
|     :layout="width >= 500 ? 'horizontal' : 'vertical'" |  | ||||||
|     :disabled="!isUpdate" |  | ||||||
|     scroll-to-first-error |  | ||||||
|     style="margin-top: 10px" |  | ||||||
|   > |  | ||||||
|     <a-list size="small" :bordered="false"> |     <a-list size="small" :bordered="false"> | ||||||
|       <a-list-item> |       <a-list-item> | ||||||
|         <a-form-item |         <a-form-item :label="securityConfig.PASSWORD_ERROR_LOCK_COUNT.name" field="PASSWORD_ERROR_LOCK_COUNT" | ||||||
|           :label="securityConfig.PASSWORD_ERROR_LOCK_COUNT.name" |           :help="securityConfig.PASSWORD_ERROR_LOCK_COUNT.description" hide-asterisk> | ||||||
|           field="PASSWORD_ERROR_LOCK_COUNT" |           <a-input-number v-model="form.PASSWORD_ERROR_LOCK_COUNT" class="input-width" :default-value="0" :precision="0" | ||||||
|           :help="securityConfig.PASSWORD_ERROR_LOCK_COUNT.description" |             :min="0" :max="10"> | ||||||
|           hide-asterisk |  | ||||||
|         > |  | ||||||
|           <a-input-number v-model="form.PASSWORD_ERROR_LOCK_COUNT" class="input-width" :default-value="0" :precision="0" :min="0" :max="10"> |  | ||||||
|             <template #append>次</template> |             <template #append>次</template> | ||||||
|           </a-input-number> |           </a-input-number> | ||||||
|         </a-form-item> |         </a-form-item> | ||||||
|       </a-list-item> |       </a-list-item> | ||||||
|       <a-list-item> |       <a-list-item> | ||||||
|         <a-form-item |         <a-form-item :label="securityConfig.PASSWORD_ERROR_LOCK_MINUTES.name" field="PASSWORD_ERROR_LOCK_MINUTES" | ||||||
|           :label="securityConfig.PASSWORD_ERROR_LOCK_MINUTES.name" |           :help="securityConfig.PASSWORD_ERROR_LOCK_MINUTES.description" hide-asterisk> | ||||||
|           field="PASSWORD_ERROR_LOCK_MINUTES" |           <a-input-number v-model="form.PASSWORD_ERROR_LOCK_MINUTES" class="input-width" :precision="0" :min="1" | ||||||
|           :help="securityConfig.PASSWORD_ERROR_LOCK_MINUTES.description" |             :max="1440"> | ||||||
|           hide-asterisk |  | ||||||
|         > |  | ||||||
|           <a-input-number v-model="form.PASSWORD_ERROR_LOCK_MINUTES" class="input-width" :precision="0" :min="1" :max="1440"> |  | ||||||
|             <template #append>分钟</template> |             <template #append>分钟</template> | ||||||
|           </a-input-number> |           </a-input-number> | ||||||
|         </a-form-item> |         </a-form-item> | ||||||
|       </a-list-item> |       </a-list-item> | ||||||
|       <a-list-item> |       <a-list-item> | ||||||
|         <a-form-item |         <a-form-item :label="securityConfig.PASSWORD_EXPIRATION_DAYS.name" field="PASSWORD_EXPIRATION_DAYS" | ||||||
|           :label="securityConfig.PASSWORD_EXPIRATION_DAYS.name" |           :help="securityConfig.PASSWORD_EXPIRATION_DAYS.description" hide-asterisk> | ||||||
|           field="PASSWORD_EXPIRATION_DAYS" |           <a-input-number v-model="form.PASSWORD_EXPIRATION_DAYS" class="input-width" :precision="0" :min="0" | ||||||
|           :help="securityConfig.PASSWORD_EXPIRATION_DAYS.description" |             :max="999"> | ||||||
|           hide-asterisk |  | ||||||
|         > |  | ||||||
|           <a-input-number v-model="form.PASSWORD_EXPIRATION_DAYS" class="input-width" :precision="0" :min="0" :max="999"> |  | ||||||
|             <template #append>天</template> |             <template #append>天</template> | ||||||
|           </a-input-number> |           </a-input-number> | ||||||
|         </a-form-item> |         </a-form-item> | ||||||
|       </a-list-item> |       </a-list-item> | ||||||
|       <a-list-item> |       <a-list-item> | ||||||
|         <a-form-item |         <a-form-item :label="securityConfig.PASSWORD_EXPIRATION_WARNING_DAYS.name" | ||||||
|           :label="securityConfig.PASSWORD_EXPIRATION_WARNING_DAYS.name" |           field="PASSWORD_EXPIRATION_WARNING_DAYS" :help="securityConfig.PASSWORD_EXPIRATION_WARNING_DAYS.description" | ||||||
|           field="PASSWORD_EXPIRATION_WARNING_DAYS" |           hide-asterisk> | ||||||
|           :help="securityConfig.PASSWORD_EXPIRATION_WARNING_DAYS.description" |           <a-input-number v-model="form.PASSWORD_EXPIRATION_WARNING_DAYS" class="input-width" :precision="0" :min="0" | ||||||
|           hide-asterisk |             :max="998"> | ||||||
|         > |  | ||||||
|           <a-input-number v-model="form.PASSWORD_EXPIRATION_WARNING_DAYS" class="input-width" :precision="0" :min="0" :max="998"> |  | ||||||
|             <template #append>天</template> |             <template #append>天</template> | ||||||
|           </a-input-number> |           </a-input-number> | ||||||
|         </a-form-item> |         </a-form-item> | ||||||
|       </a-list-item> |       </a-list-item> | ||||||
|       <a-list-item> |       <a-list-item> | ||||||
|         <a-form-item |         <a-form-item :label="securityConfig.PASSWORD_REUSE_POLICY.name" field="PASSWORD_REUSE_POLICY" | ||||||
|           :label="securityConfig.PASSWORD_REUSE_POLICY.name" |           :help="securityConfig.PASSWORD_REUSE_POLICY.description" hide-asterisk> | ||||||
|           field="PASSWORD_REUSE_POLICY" |  | ||||||
|           :help="securityConfig.PASSWORD_REUSE_POLICY.description" |  | ||||||
|           hide-asterisk |  | ||||||
|         > |  | ||||||
|           <a-input-number v-model="form.PASSWORD_REUSE_POLICY" class="input-width" :precision="0" :min="3" :max="32"> |           <a-input-number v-model="form.PASSWORD_REUSE_POLICY" class="input-width" :precision="0" :min="3" :max="32"> | ||||||
|             <template #append>次</template> |             <template #append>次</template> | ||||||
|           </a-input-number> |           </a-input-number> | ||||||
|         </a-form-item> |         </a-form-item> | ||||||
|       </a-list-item> |       </a-list-item> | ||||||
|       <a-list-item> |       <a-list-item> | ||||||
|         <a-form-item |         <a-form-item :label="securityConfig.PASSWORD_MIN_LENGTH.name" field="PASSWORD_MIN_LENGTH" | ||||||
|           :label="securityConfig.PASSWORD_MIN_LENGTH.name" |           :help="securityConfig.PASSWORD_MIN_LENGTH.description" hide-asterisk> | ||||||
|           field="PASSWORD_MIN_LENGTH" |  | ||||||
|           :help="securityConfig.PASSWORD_MIN_LENGTH.description" |  | ||||||
|           hide-asterisk |  | ||||||
|         > |  | ||||||
|           <a-input-number v-model="form.PASSWORD_MIN_LENGTH" class="input-width" :precision="0" :min="8" :max="32" /> |           <a-input-number v-model="form.PASSWORD_MIN_LENGTH" class="input-width" :precision="0" :min="8" :max="32" /> | ||||||
|         </a-form-item> |         </a-form-item> | ||||||
|       </a-list-item> |       </a-list-item> | ||||||
|       <a-list-item> |       <a-list-item> | ||||||
|         <a-form-item |         <a-form-item :label="securityConfig.PASSWORD_ALLOW_CONTAIN_USERNAME.name" | ||||||
|           :label="securityConfig.PASSWORD_ALLOW_CONTAIN_USERNAME.name" |           field="PASSWORD_ALLOW_CONTAIN_USERNAME"> | ||||||
|           field="PASSWORD_ALLOW_CONTAIN_USERNAME" |  | ||||||
|         > |  | ||||||
|           <a-switch v-model="form.PASSWORD_ALLOW_CONTAIN_USERNAME" type="round" :checked-value="1" :unchecked-value="0"> |           <a-switch v-model="form.PASSWORD_ALLOW_CONTAIN_USERNAME" type="round" :checked-value="1" :unchecked-value="0"> | ||||||
|             <template #checked>是</template> |             <template #checked>是</template> | ||||||
|             <template #unchecked>否</template> |             <template #unchecked>否</template> | ||||||
| @@ -94,11 +64,10 @@ | |||||||
|         </a-form-item> |         </a-form-item> | ||||||
|       </a-list-item> |       </a-list-item> | ||||||
|       <a-list-item> |       <a-list-item> | ||||||
|         <a-form-item |         <a-form-item :label="securityConfig.PASSWORD_CONTAIN_SPECIAL_CHARACTERS.name" | ||||||
|           :label="securityConfig.PASSWORD_CONTAIN_SPECIAL_CHARACTERS.name" |           field="PASSWORD_CONTAIN_SPECIAL_CHARACTERS"> | ||||||
|           field="PASSWORD_CONTAIN_SPECIAL_CHARACTERS" |           <a-switch v-model="form.PASSWORD_CONTAIN_SPECIAL_CHARACTERS" type="round" :checked-value="1" | ||||||
|         > |             :unchecked-value="0"> | ||||||
|           <a-switch v-model="form.PASSWORD_CONTAIN_SPECIAL_CHARACTERS" type="round" :checked-value="1" :unchecked-value="0"> |  | ||||||
|             <template #checked>是</template> |             <template #checked>是</template> | ||||||
|             <template #unchecked>否</template> |             <template #unchecked>否</template> | ||||||
|           </a-switch> |           </a-switch> | ||||||
| @@ -148,6 +117,7 @@ import { type FormInstance, Message, Modal } from '@arco-design/web-vue' | |||||||
| import { type OptionResp, type SecurityConfig, listOption, resetOptionValue, updateOption } from '@/apis' | import { type OptionResp, type SecurityConfig, listOption, resetOptionValue, updateOption } from '@/apis' | ||||||
| import { useForm } from '@/hooks' | import { useForm } from '@/hooks' | ||||||
|  |  | ||||||
|  | defineOptions({ name: 'SecuritySetting' }) | ||||||
| const { width } = useWindowSize() | const { width } = useWindowSize() | ||||||
|  |  | ||||||
| const formRef = ref<FormInstance>() | const formRef = ref<FormInstance>() | ||||||
|   | |||||||
| @@ -1,27 +1,46 @@ | |||||||
| <template> | <template> | ||||||
|   <div class="gi_page"> |   <div class="gi_page"> | ||||||
|     <a-card class="general-card" title="系统配置"> |     <a-card class="general-card" title="系统配置"> | ||||||
|       <a-tabs default-active-key="1" type="rounded"> |       <a-tabs v-model:active-key="activeKey" hide-content type="rounded" @change="change"> | ||||||
|         <a-tab-pane key="1" title="基础配置"> |         <a-tab-pane key="1" title="基础配置" /> | ||||||
|           <BasicSetting /> |         <a-tab-pane key="2" title="邮件配置" /> | ||||||
|         </a-tab-pane> |         <a-tab-pane key="3" title="安全配置" /> | ||||||
|         <a-tab-pane key="2" title="邮件配置"> |  | ||||||
|           <MailSetting /> |  | ||||||
|         </a-tab-pane> |  | ||||||
|         <a-tab-pane key="3" title="安全配置"> |  | ||||||
|           <SecuritySetting /> |  | ||||||
|         </a-tab-pane> |  | ||||||
|       </a-tabs> |       </a-tabs> | ||||||
|  |       <keep-alive> | ||||||
|  |         <component :is="PanMap[activeKey]" /> | ||||||
|  |       </keep-alive> | ||||||
|     </a-card> |     </a-card> | ||||||
|   </div> |   </div> | ||||||
| </template> | </template> | ||||||
|  |  | ||||||
| <script setup lang="ts"> | <script setup lang="ts"> | ||||||
|  | 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 MailSetting from './components/MailSetting.vue' | ||||||
| import SecuritySetting from './components/SecuritySetting.vue' | import SecuritySetting from './components/SecuritySetting.vue' | ||||||
|  |  | ||||||
| defineOptions({ name: 'SystemConfig' }) | defineOptions({ name: 'SystemConfig' }) | ||||||
|  | const PanMap: Record<string, Component> = { | ||||||
|  |   1: BasicSetting, | ||||||
|  |   2: MailSetting, | ||||||
|  |   3: SecuritySetting | ||||||
|  | } | ||||||
|  | const route = useRoute() | ||||||
|  | const router = useRouter() | ||||||
|  | const activeKey = ref('1') | ||||||
|  | watch( | ||||||
|  |   () => route.query, | ||||||
|  |   () => { | ||||||
|  |     if (route.query.tabKey) { | ||||||
|  |       activeKey.value = String(route.query.tabKey) | ||||||
|  |     } | ||||||
|  |   }, | ||||||
|  |   { immediate: true } | ||||||
|  | ) | ||||||
|  | const change = (key: string | number) => { | ||||||
|  |   activeKey.value = key as string | ||||||
|  |   router.replace({ path: route.path, query: { tabKey: key } }) | ||||||
|  | } | ||||||
| </script> | </script> | ||||||
|  |  | ||||||
| <style scoped lang="less"> | <style scoped lang="less"> | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user
	 秋帆
					秋帆