mirror of
				https://github.com/continew-org/continew-admin-ui.git
				synced 2025-11-04 20:59:23 +08:00 
			
		
		
		
	refactor: 优化系统配置相关代码
This commit is contained in:
		@@ -14,6 +14,7 @@ defineOptions({ name: 'App' })
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
const appStore = useAppStore()
 | 
					const appStore = useAppStore()
 | 
				
			||||||
appStore.initTheme()
 | 
					appStore.initTheme()
 | 
				
			||||||
 | 
					appStore.initSiteConfig()
 | 
				
			||||||
</script>
 | 
					</script>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
<style lang="scss" scoped>
 | 
					<style lang="scss" scoped>
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -25,9 +25,9 @@ export function listCommonDict(code: string) {
 | 
				
			|||||||
  return http.get<LabelValueState[]>(`${BASE_URL}/dict/${code}`)
 | 
					  return http.get<LabelValueState[]>(`${BASE_URL}/dict/${code}`)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/** @desc 获取系统参数 */
 | 
					/** @desc 查询参数列表 */
 | 
				
			||||||
export function listOption(params: OptionQuery) {
 | 
					export function listOptionDict(query: OptionQuery) {
 | 
				
			||||||
  return http.get<LabelValueState[]>(`${BASE_URL}/option`, params)
 | 
					  return http.get<LabelValueState[]>(`${BASE_URL}/dict/option`, query)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/** @desc 上传文件 */
 | 
					/** @desc 上传文件 */
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,19 +0,0 @@
 | 
				
			|||||||
import http from '@/utils/http'
 | 
					 | 
				
			||||||
import type * as System from './type'
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
const BASE_URL = '/system/option'
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/** @desc 获取系统配置参数 */
 | 
					 | 
				
			||||||
export function list(params: System.OptionQuery) {
 | 
					 | 
				
			||||||
  return http.get<System.OptionResp[]>(`${BASE_URL}`, params)
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/** @desc 保存系统参数 */
 | 
					 | 
				
			||||||
export function save(req: System.OptionReq[]) {
 | 
					 | 
				
			||||||
  return http.patch(`${BASE_URL}`, req)
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/** @desc 重置系统参数 */
 | 
					 | 
				
			||||||
export function resetValue(params: System.OptionQuery) {
 | 
					 | 
				
			||||||
  return http.patch(`${BASE_URL}/value`, params)
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
@@ -6,4 +6,4 @@ export * from '../monitor/log'
 | 
				
			|||||||
export * from './dict'
 | 
					export * from './dict'
 | 
				
			||||||
export * from './file'
 | 
					export * from './file'
 | 
				
			||||||
export * from './storage'
 | 
					export * from './storage'
 | 
				
			||||||
export * from './config'
 | 
					export * from './option'
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										19
									
								
								src/apis/system/option.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										19
									
								
								src/apis/system/option.ts
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,19 @@
 | 
				
			|||||||
 | 
					import http from '@/utils/http'
 | 
				
			||||||
 | 
					import type * as System from './type'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const BASE_URL = '/system/option'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/** @desc 查询参数列表 */
 | 
				
			||||||
 | 
					export function listOption(query: System.OptionQuery) {
 | 
				
			||||||
 | 
					  return http.get<System.OptionResp[]>(`${BASE_URL}`, query)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/** @desc 修改参数 */
 | 
				
			||||||
 | 
					export function updateOption(data: any) {
 | 
				
			||||||
 | 
					  return http.patch(`${BASE_URL}`, data)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/** @desc 重置参数 */
 | 
				
			||||||
 | 
					export function resetOptionValue(query: System.OptionQuery) {
 | 
				
			||||||
 | 
					  return http.patch(`${BASE_URL}/value`, query)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@@ -198,30 +198,25 @@ export interface StorageQuery extends PageQuery {
 | 
				
			|||||||
  status?: number
 | 
					  status?: number
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/** 系统参数*/
 | 
					/** 系统参数类型 */
 | 
				
			||||||
export interface OptionQuery {
 | 
					 | 
				
			||||||
  code?: Array<string>
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
export interface OptionReq {
 | 
					 | 
				
			||||||
  code: string
 | 
					 | 
				
			||||||
  value: string
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
export interface OptionResp {
 | 
					export interface OptionResp {
 | 
				
			||||||
  name?: string
 | 
					  name: string
 | 
				
			||||||
  code: string
 | 
					  code: string
 | 
				
			||||||
  value: string
 | 
					  value: string
 | 
				
			||||||
  description?: string
 | 
					  description: string
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					export interface OptionQuery {
 | 
				
			||||||
 | 
					  code: Array<string>
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/** 系统配置*/
 | 
					/** 基础配置类型 */
 | 
				
			||||||
export interface BasicConfigRecordResp {
 | 
					export interface BasicConfigResp {
 | 
				
			||||||
  site_title?: string
 | 
					  site_favicon: string
 | 
				
			||||||
  site_copyright?: string
 | 
					  site_logo: string
 | 
				
			||||||
  site_logo?: string
 | 
					  site_title: string
 | 
				
			||||||
  site_favicon?: string
 | 
					  site_copyright: string
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/** 绑定三方账号信息*/
 | 
					/** 绑定三方账号信息*/
 | 
				
			||||||
export interface BindSocialAccountRes {
 | 
					export interface BindSocialAccountRes {
 | 
				
			||||||
  source: string
 | 
					  source: string
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,8 +1,8 @@
 | 
				
			|||||||
<template>
 | 
					<template>
 | 
				
			||||||
  <section class="system-logo" :class="{ collapsed: props.collapsed }" @click="toHome">
 | 
					  <section class="system-logo" :class="{ collapsed: props.collapsed }" @click="toHome">
 | 
				
			||||||
    <img v-if="webLogo" class="logo" :src="webLogo" alt="logo" />
 | 
					    <img v-if="logo" class="logo" :src="logo" alt="logo" />
 | 
				
			||||||
    <img v-else class="logo" src="/logo.svg" alt="logo" />
 | 
					    <img v-else class="logo" src="/logo.svg" alt="logo" />
 | 
				
			||||||
    <span class="system-name">{{ webTitle }}</span>
 | 
					    <span class="system-name">{{ title }}</span>
 | 
				
			||||||
  </section>
 | 
					  </section>
 | 
				
			||||||
</template>
 | 
					</template>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -10,21 +10,17 @@
 | 
				
			|||||||
import { useAppStore } from '@/stores'
 | 
					import { useAppStore } from '@/stores'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const appStore = useAppStore()
 | 
					const appStore = useAppStore()
 | 
				
			||||||
appStore.initWebConfig()
 | 
					const title = computed(() => appStore.getTitle())
 | 
				
			||||||
 | 
					const logo = computed(() => appStore.getLogo())
 | 
				
			||||||
const webTitle = computed(() => appStore.getTitle())
 | 
					 | 
				
			||||||
const webLogo = computed(() => appStore.getLogo())
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
interface Props {
 | 
					interface Props {
 | 
				
			||||||
  collapsed?: boolean
 | 
					  collapsed?: boolean
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					 | 
				
			||||||
const props = withDefaults(defineProps<Props>(), {
 | 
					const props = withDefaults(defineProps<Props>(), {
 | 
				
			||||||
  collapsed: false
 | 
					  collapsed: false
 | 
				
			||||||
})
 | 
					})
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const router = useRouter()
 | 
					const router = useRouter()
 | 
				
			||||||
 | 
					 | 
				
			||||||
// 跳转首页
 | 
					// 跳转首页
 | 
				
			||||||
const toHome = () => {
 | 
					const toHome = () => {
 | 
				
			||||||
  router.push('/')
 | 
					  router.push('/')
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,58 +1,12 @@
 | 
				
			|||||||
import { defineStore } from 'pinia'
 | 
					import { defineStore } from 'pinia'
 | 
				
			||||||
 | 
					import { listOptionDict, type BasicConfigResp } from '@/apis'
 | 
				
			||||||
import { computed, reactive, toRefs } from 'vue'
 | 
					import { computed, reactive, toRefs } from 'vue'
 | 
				
			||||||
import { generate, getRgbStr } from '@arco-design/color'
 | 
					import { generate, getRgbStr } from '@arco-design/color'
 | 
				
			||||||
import defaultSettings from '@/config/setting.json'
 | 
					import defaultSettings from '@/config/setting.json'
 | 
				
			||||||
import type { BasicConfigRecordResp } from '@/apis'
 | 
					 | 
				
			||||||
import { listOption } from '@/apis'
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
const storeSetup = () => {
 | 
					const storeSetup = () => {
 | 
				
			||||||
  // App配置
 | 
					  // App配置
 | 
				
			||||||
  const settingConfig = reactive({ ...defaultSettings }) as App.SettingConfig
 | 
					  const settingConfig = reactive({ ...defaultSettings }) as App.SettingConfig
 | 
				
			||||||
  // 系统配置
 | 
					 | 
				
			||||||
  const webConfig = reactive({}) as BasicConfigRecordResp
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  const getLogo = () => {
 | 
					 | 
				
			||||||
    return webConfig.site_logo
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
  const getFavicon = () => {
 | 
					 | 
				
			||||||
    return webConfig.site_favicon
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
  const getTitle = () => {
 | 
					 | 
				
			||||||
    return webConfig.site_title
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
  const getCopyright = () => {
 | 
					 | 
				
			||||||
    return webConfig.site_copyright
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  // 初始化系统配置
 | 
					 | 
				
			||||||
  const initWebConfig = () => {
 | 
					 | 
				
			||||||
    listOption({
 | 
					 | 
				
			||||||
      code: ['site_title', 'site_copyright', 'site_favicon', 'site_logo']
 | 
					 | 
				
			||||||
    }).then((res) => {
 | 
					 | 
				
			||||||
      const resMap = new Map()
 | 
					 | 
				
			||||||
      res.data.forEach((item) => {
 | 
					 | 
				
			||||||
        resMap.set(item.label, item.value)
 | 
					 | 
				
			||||||
      })
 | 
					 | 
				
			||||||
      webConfig.site_title = resMap.get('site_title')
 | 
					 | 
				
			||||||
      webConfig.site_copyright = resMap.get('site_copyright')
 | 
					 | 
				
			||||||
      webConfig.site_logo = resMap.get('site_logo')
 | 
					 | 
				
			||||||
      webConfig.site_favicon = resMap.get('site_favicon')
 | 
					 | 
				
			||||||
      document.title = resMap.get('site_title')
 | 
					 | 
				
			||||||
      document
 | 
					 | 
				
			||||||
        .querySelector('link[rel="shortcut icon"]')
 | 
					 | 
				
			||||||
        ?.setAttribute('href', resMap.get('site_favicon') || 'https://admin.continew.top/favicon.ico')
 | 
					 | 
				
			||||||
    })
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  // 保存系统配置
 | 
					 | 
				
			||||||
  const saveWebConfig = (config: BasicConfigRecordResp) => {
 | 
					 | 
				
			||||||
    Object.assign(webConfig, config)
 | 
					 | 
				
			||||||
    document.title = config.site_title || ''
 | 
					 | 
				
			||||||
    document
 | 
					 | 
				
			||||||
      .querySelector('link[rel="shortcut icon"]')
 | 
					 | 
				
			||||||
      ?.setAttribute('href', config.site_favicon || 'https://admin.continew.top/favicon.ico')
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  // 页面切换动画类名
 | 
					  // 页面切换动画类名
 | 
				
			||||||
  const transitionName = computed(() => (settingConfig.animate ? settingConfig.animateMode : ''))
 | 
					  const transitionName = computed(() => (settingConfig.animate ? settingConfig.animateMode : ''))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -100,21 +54,66 @@ const storeSetup = () => {
 | 
				
			|||||||
    settingConfig.menuCollapse = collapsed
 | 
					    settingConfig.menuCollapse = collapsed
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  // 系统配置配置
 | 
				
			||||||
 | 
					  const siteConfig = reactive({}) as BasicConfigResp
 | 
				
			||||||
 | 
					  // 初始化系统配置
 | 
				
			||||||
 | 
					  const initSiteConfig = () => {
 | 
				
			||||||
 | 
					    listOptionDict({
 | 
				
			||||||
 | 
					      code: ['site_favicon', 'site_logo', 'site_title', 'site_copyright']
 | 
				
			||||||
 | 
					    }).then((res) => {
 | 
				
			||||||
 | 
					      const resMap = new Map()
 | 
				
			||||||
 | 
					      res.data.forEach((item) => {
 | 
				
			||||||
 | 
					        resMap.set(item.label, item.value)
 | 
				
			||||||
 | 
					      })
 | 
				
			||||||
 | 
					      siteConfig.site_logo = resMap.get('site_logo')
 | 
				
			||||||
 | 
					      siteConfig.site_favicon = resMap.get('site_favicon')
 | 
				
			||||||
 | 
					      siteConfig.site_title = resMap.get('site_title')
 | 
				
			||||||
 | 
					      siteConfig.site_copyright = resMap.get('site_copyright')
 | 
				
			||||||
 | 
					      document.title = resMap.get('site_title')
 | 
				
			||||||
 | 
					      document
 | 
				
			||||||
 | 
					        .querySelector('link[rel="shortcut icon"]')
 | 
				
			||||||
 | 
					        ?.setAttribute('href', resMap.get('site_favicon') || '/favicon.ico')
 | 
				
			||||||
 | 
					    })
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  // 设置系统配置
 | 
				
			||||||
 | 
					  const setSiteConfig = (config: BasicConfigResp) => {
 | 
				
			||||||
 | 
					    Object.assign(siteConfig, config)
 | 
				
			||||||
 | 
					    document.title = config.site_title || ''
 | 
				
			||||||
 | 
					    document.querySelector('link[rel="shortcut icon"]')?.setAttribute('href', config.site_favicon || '/favicon.ico')
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  const getFavicon = () => {
 | 
				
			||||||
 | 
					    return siteConfig.site_favicon
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  const getLogo = () => {
 | 
				
			||||||
 | 
					    return siteConfig.site_logo
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  const getTitle = () => {
 | 
				
			||||||
 | 
					    return siteConfig.site_title
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  const getCopyright = () => {
 | 
				
			||||||
 | 
					    return siteConfig.site_copyright
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  return {
 | 
					  return {
 | 
				
			||||||
    ...toRefs(settingConfig),
 | 
					    ...toRefs(settingConfig),
 | 
				
			||||||
    ...toRefs(webConfig),
 | 
					    ...toRefs(siteConfig),
 | 
				
			||||||
    transitionName,
 | 
					    transitionName,
 | 
				
			||||||
    themeCSSVar,
 | 
					    themeCSSVar,
 | 
				
			||||||
    toggleTheme,
 | 
					    toggleTheme,
 | 
				
			||||||
    setThemeColor,
 | 
					    setThemeColor,
 | 
				
			||||||
    initTheme,
 | 
					    initTheme,
 | 
				
			||||||
    setMenuCollapse,
 | 
					    setMenuCollapse,
 | 
				
			||||||
    getLogo,
 | 
					    initSiteConfig,
 | 
				
			||||||
 | 
					    setSiteConfig,
 | 
				
			||||||
    getFavicon,
 | 
					    getFavicon,
 | 
				
			||||||
 | 
					    getLogo,
 | 
				
			||||||
    getTitle,
 | 
					    getTitle,
 | 
				
			||||||
    getCopyright,
 | 
					    getCopyright
 | 
				
			||||||
    initWebConfig,
 | 
					 | 
				
			||||||
    saveWebConfig
 | 
					 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -87,7 +87,6 @@ import { useLoading } from '@/hooks'
 | 
				
			|||||||
import { encryptByRsa } from '@/utils/encrypt'
 | 
					import { encryptByRsa } from '@/utils/encrypt'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const appStore = useAppStore()
 | 
					const appStore = useAppStore()
 | 
				
			||||||
appStore.initWebConfig()
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
computed(() => appStore.getTitle())
 | 
					computed(() => appStore.getTitle())
 | 
				
			||||||
const webLogo = computed(() => appStore.getLogo())
 | 
					const webLogo = computed(() => appStore.getLogo())
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,8 +1,8 @@
 | 
				
			|||||||
<template>
 | 
					<template>
 | 
				
			||||||
  <a-form ref="formRef" layout="vertical" :model="form" :rules="rules" size="large" :disabled="!isEdit">
 | 
					  <a-form ref="formRef" :model="form" :rules="rules" size="large" layout="vertical" :disabled="!isUpdate">
 | 
				
			||||||
    <a-list class="list-layout" :bordered="false">
 | 
					    <a-list class="list-layout" :bordered="false">
 | 
				
			||||||
      <a-list-item>
 | 
					      <a-list-item>
 | 
				
			||||||
        <a-form-item class="image-item" hide-label field="favicon">
 | 
					        <a-form-item class="image-item" hide-label field="site_favicon">
 | 
				
			||||||
          {{ siteFavicon?.name }}
 | 
					          {{ siteFavicon?.name }}
 | 
				
			||||||
          <template #extra>
 | 
					          <template #extra>
 | 
				
			||||||
            {{ siteFavicon?.description }}
 | 
					            {{ siteFavicon?.description }}
 | 
				
			||||||
@@ -25,7 +25,7 @@
 | 
				
			|||||||
                    class="arco-upload-list-picture custom-upload-avatar favicon"
 | 
					                    class="arco-upload-list-picture custom-upload-avatar favicon"
 | 
				
			||||||
                  >
 | 
					                  >
 | 
				
			||||||
                    <img :src="faviconFile.url" alt="favicon" />
 | 
					                    <img :src="faviconFile.url" alt="favicon" />
 | 
				
			||||||
                    <div v-if="isEdit" class="arco-upload-list-picture-mask favicon">
 | 
					                    <div v-if="isUpdate" class="arco-upload-list-picture-mask favicon">
 | 
				
			||||||
                      <IconEdit />
 | 
					                      <IconEdit />
 | 
				
			||||||
                    </div>
 | 
					                    </div>
 | 
				
			||||||
                  </div>
 | 
					                  </div>
 | 
				
			||||||
@@ -61,7 +61,7 @@
 | 
				
			|||||||
                >
 | 
					                >
 | 
				
			||||||
                  <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="isEdit" class="arco-upload-list-picture-mask logo">
 | 
					                    <div v-if="isUpdate" class="arco-upload-list-picture-mask logo">
 | 
				
			||||||
                      <IconEdit />
 | 
					                      <IconEdit />
 | 
				
			||||||
                    </div>
 | 
					                    </div>
 | 
				
			||||||
                  </div>
 | 
					                  </div>
 | 
				
			||||||
@@ -78,11 +78,11 @@
 | 
				
			|||||||
      </a-list-item>
 | 
					      </a-list-item>
 | 
				
			||||||
      <a-list-item style="padding-top: 13px; border: none">
 | 
					      <a-list-item style="padding-top: 13px; border: none">
 | 
				
			||||||
        <a-form-item class="input-item" :label="siteTitle?.name" field="site_title">
 | 
					        <a-form-item class="input-item" :label="siteTitle?.name" field="site_title">
 | 
				
			||||||
          <a-input v-model="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="form.site_copyright"
 | 
					            v-model.trim="form.site_copyright"
 | 
				
			||||||
            placeholder="请输入版权信息"
 | 
					            placeholder="请输入版权信息"
 | 
				
			||||||
            :auto-size="{
 | 
					            :auto-size="{
 | 
				
			||||||
              minRows: 3
 | 
					              minRows: 3
 | 
				
			||||||
@@ -92,31 +92,31 @@
 | 
				
			|||||||
        </a-form-item>
 | 
					        </a-form-item>
 | 
				
			||||||
        <div style="margin-top: 20px">
 | 
					        <div style="margin-top: 20px">
 | 
				
			||||||
          <a-space>
 | 
					          <a-space>
 | 
				
			||||||
            <a-button v-if="!isEdit" @click="toResetValue">
 | 
					            <a-button v-if="!isUpdate" @click="onResetValue">
 | 
				
			||||||
              <template #icon>
 | 
					              <template #icon>
 | 
				
			||||||
                <icon-undo />
 | 
					                <icon-undo />
 | 
				
			||||||
              </template>
 | 
					              </template>
 | 
				
			||||||
              恢复默认
 | 
					              恢复默认
 | 
				
			||||||
            </a-button>
 | 
					            </a-button>
 | 
				
			||||||
            <a-button v-if="!isEdit" type="primary" @click="toEdit">
 | 
					            <a-button v-if="!isUpdate" type="primary" @click="onUpdate">
 | 
				
			||||||
              <template #icon>
 | 
					              <template #icon>
 | 
				
			||||||
                <icon-edit />
 | 
					                <icon-edit />
 | 
				
			||||||
              </template>
 | 
					              </template>
 | 
				
			||||||
              修改
 | 
					              修改
 | 
				
			||||||
            </a-button>
 | 
					            </a-button>
 | 
				
			||||||
            <a-button v-if="isEdit" type="primary" @click="handleSave">
 | 
					            <a-button v-if="isUpdate" type="primary" @click="handleSave">
 | 
				
			||||||
              <template #icon>
 | 
					              <template #icon>
 | 
				
			||||||
                <icon-save />
 | 
					                <icon-save />
 | 
				
			||||||
              </template>
 | 
					              </template>
 | 
				
			||||||
              保存
 | 
					              保存
 | 
				
			||||||
            </a-button>
 | 
					            </a-button>
 | 
				
			||||||
            <a-button v-if="isEdit" @click="reset">
 | 
					            <a-button v-if="isUpdate" @click="reset">
 | 
				
			||||||
              <template #icon>
 | 
					              <template #icon>
 | 
				
			||||||
                <icon-refresh />
 | 
					                <icon-refresh />
 | 
				
			||||||
              </template>
 | 
					              </template>
 | 
				
			||||||
              重置
 | 
					              重置
 | 
				
			||||||
            </a-button>
 | 
					            </a-button>
 | 
				
			||||||
            <a-button v-if="isEdit" @click="handleCancel">
 | 
					            <a-button v-if="isUpdate" @click="handleCancel">
 | 
				
			||||||
              <template #icon>
 | 
					              <template #icon>
 | 
				
			||||||
                <icon-undo />
 | 
					                <icon-undo />
 | 
				
			||||||
              </template>
 | 
					              </template>
 | 
				
			||||||
@@ -130,130 +130,102 @@
 | 
				
			|||||||
</template>
 | 
					</template>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
<script lang="ts" setup>
 | 
					<script lang="ts" setup>
 | 
				
			||||||
import type { OptionResp } from '@/apis'
 | 
					import { listOption, updateOption, resetOptionValue, uploadFile, type OptionResp } from '@/apis'
 | 
				
			||||||
import { list, resetValue, save, uploadFile } from '@/apis'
 | 
					import { Message, Modal, type FileItem, type FormInstance, type RequestOption } from '@arco-design/web-vue'
 | 
				
			||||||
import { useAppStore } from '@/stores'
 | 
					import { useAppStore } from '@/stores'
 | 
				
			||||||
import { type FileItem, type FormInstance, type RequestOption, Message, Modal } from '@arco-design/web-vue'
 | 
					 | 
				
			||||||
import { useForm } from '@/hooks'
 | 
					import { useForm } from '@/hooks'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const formRef = ref<FormInstance>()
 | 
					const formRef = ref<FormInstance>()
 | 
				
			||||||
const dataList = ref<OptionResp[]>([])
 | 
					 | 
				
			||||||
const isEdit = ref(false)
 | 
					 | 
				
			||||||
const logoFile = ref<FileItem>({ uid: '-1' })
 | 
					 | 
				
			||||||
const faviconFile = ref<FileItem>({ uid: '-2' })
 | 
					 | 
				
			||||||
const siteTitle = ref<OptionResp>()
 | 
					 | 
				
			||||||
const siteCopyright = ref<OptionResp>()
 | 
					 | 
				
			||||||
const siteLogo = ref<OptionResp>()
 | 
					 | 
				
			||||||
const siteFavicon = ref<OptionResp>()
 | 
					 | 
				
			||||||
const appStore = useAppStore()
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
const rules: FormInstance['rules'] = {
 | 
					const rules: FormInstance['rules'] = {
 | 
				
			||||||
  site_title: [{ required: true, message: '请输入系统标题' }],
 | 
					  site_title: [{ required: true, message: '请输入系统标题' }],
 | 
				
			||||||
  site_copyright: [{ required: true, message: '请输入版权信息' }]
 | 
					  site_copyright: [{ required: true, message: '请输入版权信息' }]
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const { form } = useForm({
 | 
					const { form } = useForm({
 | 
				
			||||||
  site_title: '',
 | 
					  site_favicon: '',
 | 
				
			||||||
  site_copyright: '',
 | 
					 | 
				
			||||||
  site_logo: '',
 | 
					  site_logo: '',
 | 
				
			||||||
  site_favicon: ''
 | 
					  site_title: '',
 | 
				
			||||||
 | 
					  site_copyright: ''
 | 
				
			||||||
})
 | 
					})
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const query = reactive({
 | 
					const siteFavicon = ref<OptionResp>()
 | 
				
			||||||
  queryParams: {
 | 
					const siteLogo = ref<OptionResp>()
 | 
				
			||||||
    code: ['site_title', 'site_copyright', 'site_logo', 'site_favicon']
 | 
					const siteTitle = ref<OptionResp>()
 | 
				
			||||||
  }
 | 
					const siteCopyright = ref<OptionResp>()
 | 
				
			||||||
})
 | 
					const faviconFile = ref<FileItem>({ uid: '-1' })
 | 
				
			||||||
 | 
					const logoFile = ref<FileItem>({ uid: '-2' })
 | 
				
			||||||
/**
 | 
					// 重置
 | 
				
			||||||
 * 重置表单
 | 
					 | 
				
			||||||
 */
 | 
					 | 
				
			||||||
const reset = () => {
 | 
					const reset = () => {
 | 
				
			||||||
 | 
					  form.site_favicon = siteFavicon.value?.value || ''
 | 
				
			||||||
 | 
					  form.site_logo = siteLogo.value?.value || ''
 | 
				
			||||||
  form.site_title = siteTitle.value?.value || ''
 | 
					  form.site_title = siteTitle.value?.value || ''
 | 
				
			||||||
  form.site_copyright = siteCopyright.value?.value || ''
 | 
					  form.site_copyright = siteCopyright.value?.value || ''
 | 
				
			||||||
  form.site_logo = siteLogo.value?.value || ''
 | 
					 | 
				
			||||||
  form.site_favicon = siteFavicon.value?.value || ''
 | 
					 | 
				
			||||||
  logoFile.value.url = siteLogo.value?.value
 | 
					 | 
				
			||||||
  faviconFile.value.url = siteFavicon.value?.value
 | 
					  faviconFile.value.url = siteFavicon.value?.value
 | 
				
			||||||
 | 
					  logoFile.value.url = siteLogo.value?.value
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/**
 | 
					const isUpdate = ref(false)
 | 
				
			||||||
 * 查询配置
 | 
					// 修改
 | 
				
			||||||
 */
 | 
					const onUpdate = () => {
 | 
				
			||||||
const getConfig = async () => {
 | 
					  isUpdate.value = true
 | 
				
			||||||
  const res = await list(query.queryParams)
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// 取消
 | 
				
			||||||
 | 
					const handleCancel = () => {
 | 
				
			||||||
 | 
					  isUpdate.value = false
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const dataList = ref<OptionResp[]>([])
 | 
				
			||||||
 | 
					const queryForm = reactive({
 | 
				
			||||||
 | 
					  code: ['site_title', 'site_copyright', 'site_logo', 'site_favicon']
 | 
				
			||||||
 | 
					})
 | 
				
			||||||
 | 
					// 查询列表数据
 | 
				
			||||||
 | 
					const getDataList = async () => {
 | 
				
			||||||
 | 
					  const res = await listOption(queryForm)
 | 
				
			||||||
  dataList.value = res.data
 | 
					  dataList.value = res.data
 | 
				
			||||||
 | 
					  siteFavicon.value = dataList.value.find((option) => option.code === 'site_favicon')
 | 
				
			||||||
 | 
					  siteLogo.value = dataList.value.find((option) => option.code === 'site_logo')
 | 
				
			||||||
  siteTitle.value = dataList.value.find((option) => option.code === 'site_title')
 | 
					  siteTitle.value = dataList.value.find((option) => option.code === 'site_title')
 | 
				
			||||||
  siteCopyright.value = dataList.value.find((option) => option.code === 'site_copyright')
 | 
					  siteCopyright.value = dataList.value.find((option) => option.code === 'site_copyright')
 | 
				
			||||||
  siteLogo.value = dataList.value.find((option) => option.code === 'site_logo')
 | 
					 | 
				
			||||||
  siteFavicon.value = dataList.value.find((option) => option.code === 'site_favicon')
 | 
					 | 
				
			||||||
  reset()
 | 
					  reset()
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
getConfig()
 | 
					const appStore = useAppStore()
 | 
				
			||||||
 | 
					// 保存
 | 
				
			||||||
/**
 | 
					const handleSave = async () => {
 | 
				
			||||||
 * 取消
 | 
					  const isInvalid = await formRef.value?.validate()
 | 
				
			||||||
 */
 | 
					  if (isInvalid) return false
 | 
				
			||||||
const handleCancel = () => {
 | 
					  await updateOption(
 | 
				
			||||||
  isEdit.value = false
 | 
					    Object.entries(form).map((item) => {
 | 
				
			||||||
 | 
					      return {
 | 
				
			||||||
 | 
					        code: item[0],
 | 
				
			||||||
 | 
					        value: item[1]
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					    })
 | 
				
			||||||
 | 
					  )
 | 
				
			||||||
 | 
					  appStore.setSiteConfig(form)
 | 
				
			||||||
 | 
					  handleCancel()
 | 
				
			||||||
 | 
					  Message.success('保存成功')
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/**
 | 
					// 恢复默认
 | 
				
			||||||
 * 保存
 | 
					const handleResetValue = async () => {
 | 
				
			||||||
 */
 | 
					  await resetOptionValue(queryForm)
 | 
				
			||||||
const handleSave = () => {
 | 
					  Message.success('恢复成功')
 | 
				
			||||||
  formRef.value?.validate((valid: any) => {
 | 
					  await getDataList()
 | 
				
			||||||
    if (!valid) {
 | 
					  appStore.setSiteConfig(form)
 | 
				
			||||||
      const optionList: OptionResp[] = Object.entries(form).map((item) => {
 | 
					}
 | 
				
			||||||
        return {
 | 
					const onResetValue = () => {
 | 
				
			||||||
          code: item[0],
 | 
					  Modal.warning({
 | 
				
			||||||
          value: item[1]
 | 
					    title: '警告',
 | 
				
			||||||
        }
 | 
					    content: '确认恢复基础配置为默认值吗?',
 | 
				
			||||||
      })
 | 
					    hideCancel: false,
 | 
				
			||||||
      save(optionList).then((res) => {
 | 
					    maskClosable: false,
 | 
				
			||||||
        appStore.saveWebConfig(form)
 | 
					    onOk: handleResetValue
 | 
				
			||||||
        handleCancel()
 | 
					 | 
				
			||||||
        Message.success(res.msg)
 | 
					 | 
				
			||||||
      })
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
  })
 | 
					  })
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/**
 | 
					// 上传 favicon
 | 
				
			||||||
 * 上传 Logo
 | 
					 | 
				
			||||||
 *
 | 
					 | 
				
			||||||
 * @param options /
 | 
					 | 
				
			||||||
 */
 | 
					 | 
				
			||||||
const handleUploadLogo = (options: RequestOption) => {
 | 
					 | 
				
			||||||
  const controller = new AbortController()
 | 
					 | 
				
			||||||
  ;(async function requestWrap() {
 | 
					 | 
				
			||||||
    const { onProgress, onError, onSuccess, fileItem, name = 'file' } = options
 | 
					 | 
				
			||||||
    onProgress(20)
 | 
					 | 
				
			||||||
    const formData = new FormData()
 | 
					 | 
				
			||||||
    formData.append(name as string, fileItem.file as Blob)
 | 
					 | 
				
			||||||
    uploadFile(formData)
 | 
					 | 
				
			||||||
      .then((res) => {
 | 
					 | 
				
			||||||
        onSuccess(res)
 | 
					 | 
				
			||||||
        form.site_logo = res.data.url
 | 
					 | 
				
			||||||
        Message.success(res.msg)
 | 
					 | 
				
			||||||
      })
 | 
					 | 
				
			||||||
      .catch((error) => {
 | 
					 | 
				
			||||||
        onError(error)
 | 
					 | 
				
			||||||
      })
 | 
					 | 
				
			||||||
  })()
 | 
					 | 
				
			||||||
  return {
 | 
					 | 
				
			||||||
    abort() {
 | 
					 | 
				
			||||||
      controller.abort()
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/**
 | 
					 | 
				
			||||||
 * 上传 Favicon
 | 
					 | 
				
			||||||
 *
 | 
					 | 
				
			||||||
 * @param options /
 | 
					 | 
				
			||||||
 */
 | 
					 | 
				
			||||||
const handleUploadFavicon = (options: RequestOption) => {
 | 
					const handleUploadFavicon = (options: RequestOption) => {
 | 
				
			||||||
  const controller = new AbortController()
 | 
					  const controller = new AbortController()
 | 
				
			||||||
  ;(async function requestWrap() {
 | 
					  ;(async function requestWrap() {
 | 
				
			||||||
@@ -265,7 +237,7 @@ const handleUploadFavicon = (options: RequestOption) => {
 | 
				
			|||||||
      .then((res) => {
 | 
					      .then((res) => {
 | 
				
			||||||
        onSuccess(res)
 | 
					        onSuccess(res)
 | 
				
			||||||
        form.site_favicon = res.data.url
 | 
					        form.site_favicon = res.data.url
 | 
				
			||||||
        Message.success(res.msg)
 | 
					        Message.success('上传成功')
 | 
				
			||||||
      })
 | 
					      })
 | 
				
			||||||
      .catch((error) => {
 | 
					      .catch((error) => {
 | 
				
			||||||
        onError(error)
 | 
					        onError(error)
 | 
				
			||||||
@@ -277,63 +249,48 @@ const handleUploadFavicon = (options: RequestOption) => {
 | 
				
			|||||||
    }
 | 
					    }
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					 | 
				
			||||||
/**
 | 
					 | 
				
			||||||
 * 选择 Logo
 | 
					 | 
				
			||||||
 *
 | 
					 | 
				
			||||||
 * @param _ /
 | 
					 | 
				
			||||||
 * @param currentFile
 | 
					 | 
				
			||||||
 */
 | 
					 | 
				
			||||||
const handleChangeLogo = (_: any, currentFile: any) => {
 | 
					 | 
				
			||||||
  logoFile.value = {
 | 
					 | 
				
			||||||
    ...currentFile
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/**
 | 
					 | 
				
			||||||
 * 选择 Favicon
 | 
					 | 
				
			||||||
 *
 | 
					 | 
				
			||||||
 * @param _ /
 | 
					 | 
				
			||||||
 * @param currentFile
 | 
					 | 
				
			||||||
 */
 | 
					 | 
				
			||||||
const handleChangeFavicon = (_: any, currentFile: any) => {
 | 
					const handleChangeFavicon = (_: any, currentFile: any) => {
 | 
				
			||||||
  faviconFile.value = {
 | 
					  faviconFile.value = {
 | 
				
			||||||
    ...currentFile
 | 
					    ...currentFile
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/**
 | 
					// 上传 Logo
 | 
				
			||||||
 * 恢复默认
 | 
					const handleUploadLogo = (options: RequestOption) => {
 | 
				
			||||||
 */
 | 
					  const controller = new AbortController()
 | 
				
			||||||
const handleResetValue = async () => {
 | 
					  ;(async function requestWrap() {
 | 
				
			||||||
  await resetValue(query.queryParams)
 | 
					    const { onProgress, onError, onSuccess, fileItem, name = 'file' } = options
 | 
				
			||||||
  Message.success('恢复成功')
 | 
					    onProgress(20)
 | 
				
			||||||
  await getConfig()
 | 
					    const formData = new FormData()
 | 
				
			||||||
  appStore.saveWebConfig(form)
 | 
					    formData.append(name as string, fileItem.file as Blob)
 | 
				
			||||||
 | 
					    uploadFile(formData)
 | 
				
			||||||
 | 
					      .then((res) => {
 | 
				
			||||||
 | 
					        onSuccess(res)
 | 
				
			||||||
 | 
					        form.site_logo = res.data.url
 | 
				
			||||||
 | 
					        Message.success('上传成功')
 | 
				
			||||||
 | 
					      })
 | 
				
			||||||
 | 
					      .catch((error) => {
 | 
				
			||||||
 | 
					        onError(error)
 | 
				
			||||||
 | 
					      })
 | 
				
			||||||
 | 
					  })()
 | 
				
			||||||
 | 
					  return {
 | 
				
			||||||
 | 
					    abort() {
 | 
				
			||||||
 | 
					      controller.abort()
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					const handleChangeLogo = (_: any, currentFile: any) => {
 | 
				
			||||||
 | 
					  logoFile.value = {
 | 
				
			||||||
 | 
					    ...currentFile
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/**
 | 
					onMounted(() => {
 | 
				
			||||||
 * 点击恢复默认
 | 
					  getDataList()
 | 
				
			||||||
 */
 | 
					})
 | 
				
			||||||
const toResetValue = () => {
 | 
					 | 
				
			||||||
  Modal.warning({
 | 
					 | 
				
			||||||
    title: '警告',
 | 
					 | 
				
			||||||
    content: '确认恢复基础配置为默认值吗?',
 | 
					 | 
				
			||||||
    hideCancel: false,
 | 
					 | 
				
			||||||
    maskClosable: false,
 | 
					 | 
				
			||||||
    onBeforeOk: handleResetValue
 | 
					 | 
				
			||||||
  })
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/**
 | 
					 | 
				
			||||||
 * 开始编辑
 | 
					 | 
				
			||||||
 */
 | 
					 | 
				
			||||||
const toEdit = () => {
 | 
					 | 
				
			||||||
  isEdit.value = true
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
</script>
 | 
					</script>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
<style scoped lang="less">
 | 
					<style lang="scss" scoped>
 | 
				
			||||||
.logo {
 | 
					.logo {
 | 
				
			||||||
  width: 33px;
 | 
					  width: 33px;
 | 
				
			||||||
  height: 33px;
 | 
					  height: 33px;
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -5,7 +5,7 @@
 | 
				
			|||||||
        <a-tab-pane key="1" title="基础配置">
 | 
					        <a-tab-pane key="1" title="基础配置">
 | 
				
			||||||
          <BasicSetting />
 | 
					          <BasicSetting />
 | 
				
			||||||
        </a-tab-pane>
 | 
					        </a-tab-pane>
 | 
				
			||||||
        <a-tab-pane key="2" title="高级配置" disabled></a-tab-pane>
 | 
					        <a-tab-pane key="2" title="邮件配置" disabled></a-tab-pane>
 | 
				
			||||||
      </a-tabs>
 | 
					      </a-tabs>
 | 
				
			||||||
    </a-card>
 | 
					    </a-card>
 | 
				
			||||||
  </div>
 | 
					  </div>
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user