mirror of
				https://gitee.com/hhyykk/ipms-sjy.git
				synced 2025-11-04 12:18:42 +08:00 
			
		
		
		
	feat: add vue3(element-plus)
This commit is contained in:
		
							
								
								
									
										3
									
								
								yudao-ui-admin-vue3/src/components/Setting/index.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										3
									
								
								yudao-ui-admin-vue3/src/components/Setting/index.ts
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,3 @@
 | 
			
		||||
import Setting from './src/Setting.vue'
 | 
			
		||||
 | 
			
		||||
export { Setting }
 | 
			
		||||
							
								
								
									
										301
									
								
								yudao-ui-admin-vue3/src/components/Setting/src/Setting.vue
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										301
									
								
								yudao-ui-admin-vue3/src/components/Setting/src/Setting.vue
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,301 @@
 | 
			
		||||
<script setup lang="ts">
 | 
			
		||||
import { ElDrawer, ElDivider, ElMessage } from 'element-plus'
 | 
			
		||||
import { ref, unref, computed, watch } from 'vue'
 | 
			
		||||
import { useI18n } from '@/hooks/web/useI18n'
 | 
			
		||||
import { ThemeSwitch } from '@/components/ThemeSwitch'
 | 
			
		||||
import { colorIsDark, lighten, hexToRGB } from '@/utils/color'
 | 
			
		||||
import { useCssVar } from '@vueuse/core'
 | 
			
		||||
import { useAppStore } from '@/store/modules/app'
 | 
			
		||||
import { trim, setCssVar } from '@/utils'
 | 
			
		||||
import ColorRadioPicker from './components/ColorRadioPicker.vue'
 | 
			
		||||
import InterfaceDisplay from './components/InterfaceDisplay.vue'
 | 
			
		||||
import LayoutRadioPicker from './components/LayoutRadioPicker.vue'
 | 
			
		||||
import { useCache } from '@/hooks/web/useCache'
 | 
			
		||||
import { useClipboard } from '@vueuse/core'
 | 
			
		||||
import { useDesign } from '@/hooks/web/useDesign'
 | 
			
		||||
 | 
			
		||||
const { getPrefixCls } = useDesign()
 | 
			
		||||
 | 
			
		||||
const prefixCls = getPrefixCls('setting')
 | 
			
		||||
 | 
			
		||||
const appStore = useAppStore()
 | 
			
		||||
 | 
			
		||||
const { t } = useI18n()
 | 
			
		||||
 | 
			
		||||
const layout = computed(() => appStore.getLayout)
 | 
			
		||||
 | 
			
		||||
const drawer = ref(false)
 | 
			
		||||
 | 
			
		||||
// 主题色相关
 | 
			
		||||
const systemTheme = ref(appStore.getTheme.elColorPrimary)
 | 
			
		||||
 | 
			
		||||
const setSystemTheme = (color: string) => {
 | 
			
		||||
  setCssVar('--el-color-primary', color)
 | 
			
		||||
  appStore.setTheme({ elColorPrimary: color })
 | 
			
		||||
  const leftMenuBgColor = useCssVar('--left-menu-bg-color', document.documentElement)
 | 
			
		||||
  setMenuTheme(trim(unref(leftMenuBgColor)))
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// 头部主题相关
 | 
			
		||||
const headerTheme = ref(appStore.getTheme.topHeaderBgColor || '')
 | 
			
		||||
 | 
			
		||||
const setHeaderTheme = (color: string) => {
 | 
			
		||||
  const isDarkColor = colorIsDark(color)
 | 
			
		||||
  const textColor = isDarkColor ? '#fff' : 'inherit'
 | 
			
		||||
  const textHoverColor = isDarkColor ? lighten(color!, 6) : '#f6f6f6'
 | 
			
		||||
  const topToolBorderColor = isDarkColor ? color : '#eee'
 | 
			
		||||
  setCssVar('--top-header-bg-color', color)
 | 
			
		||||
  setCssVar('--top-header-text-color', textColor)
 | 
			
		||||
  setCssVar('--top-header-hover-color', textHoverColor)
 | 
			
		||||
  setCssVar('--top-tool-border-color', topToolBorderColor)
 | 
			
		||||
  appStore.setTheme({
 | 
			
		||||
    topHeaderBgColor: color,
 | 
			
		||||
    topHeaderTextColor: textColor,
 | 
			
		||||
    topHeaderHoverColor: textHoverColor,
 | 
			
		||||
    topToolBorderColor
 | 
			
		||||
  })
 | 
			
		||||
  if (unref(layout) === 'top') {
 | 
			
		||||
    setMenuTheme(color)
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// 菜单主题相关
 | 
			
		||||
const menuTheme = ref(appStore.getTheme.leftMenuBgColor || '')
 | 
			
		||||
 | 
			
		||||
const setMenuTheme = (color: string) => {
 | 
			
		||||
  const primaryColor = useCssVar('--el-color-primary', document.documentElement)
 | 
			
		||||
  const isDarkColor = colorIsDark(color)
 | 
			
		||||
  const theme: Recordable = {
 | 
			
		||||
    // 左侧菜单边框颜色
 | 
			
		||||
    leftMenuBorderColor: isDarkColor ? 'inherit' : '#eee',
 | 
			
		||||
    // 左侧菜单背景颜色
 | 
			
		||||
    leftMenuBgColor: color,
 | 
			
		||||
    // 左侧菜单浅色背景颜色
 | 
			
		||||
    leftMenuBgLightColor: isDarkColor ? lighten(color!, 6) : color,
 | 
			
		||||
    // 左侧菜单选中背景颜色
 | 
			
		||||
    leftMenuBgActiveColor: isDarkColor
 | 
			
		||||
      ? 'var(--el-color-primary)'
 | 
			
		||||
      : hexToRGB(unref(primaryColor), 0.1),
 | 
			
		||||
    // 左侧菜单收起选中背景颜色
 | 
			
		||||
    leftMenuCollapseBgActiveColor: isDarkColor
 | 
			
		||||
      ? 'var(--el-color-primary)'
 | 
			
		||||
      : hexToRGB(unref(primaryColor), 0.1),
 | 
			
		||||
    // 左侧菜单字体颜色
 | 
			
		||||
    leftMenuTextColor: isDarkColor ? '#bfcbd9' : '#333',
 | 
			
		||||
    // 左侧菜单选中字体颜色
 | 
			
		||||
    leftMenuTextActiveColor: isDarkColor ? '#fff' : 'var(--el-color-primary)',
 | 
			
		||||
    // logo字体颜色
 | 
			
		||||
    logoTitleTextColor: isDarkColor ? '#fff' : 'inherit',
 | 
			
		||||
    // logo边框颜色
 | 
			
		||||
    logoBorderColor: isDarkColor ? color : '#eee'
 | 
			
		||||
  }
 | 
			
		||||
  appStore.setTheme(theme)
 | 
			
		||||
  appStore.setCssVarTheme()
 | 
			
		||||
}
 | 
			
		||||
if (layout.value === 'top' && !appStore.getIsDark) {
 | 
			
		||||
  headerTheme.value = '#fff'
 | 
			
		||||
  setHeaderTheme('#fff')
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// 监听layout变化,重置一些主题色
 | 
			
		||||
watch(
 | 
			
		||||
  () => layout.value,
 | 
			
		||||
  (n) => {
 | 
			
		||||
    if (n === 'top' && !appStore.getIsDark) {
 | 
			
		||||
      headerTheme.value = '#fff'
 | 
			
		||||
      setHeaderTheme('#fff')
 | 
			
		||||
    } else {
 | 
			
		||||
      setMenuTheme(unref(menuTheme))
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// 拷贝
 | 
			
		||||
const copyConfig = async () => {
 | 
			
		||||
  const { copy, copied, isSupported } = useClipboard({
 | 
			
		||||
    source: `
 | 
			
		||||
      // 面包屑
 | 
			
		||||
      breadcrumb: ${appStore.getBreadcrumb},
 | 
			
		||||
      // 面包屑图标
 | 
			
		||||
      breadcrumbIcon: ${appStore.getBreadcrumbIcon},
 | 
			
		||||
      // 折叠图标
 | 
			
		||||
      hamburger: ${appStore.getHamburger},
 | 
			
		||||
      // 全屏图标
 | 
			
		||||
      screenfull: ${appStore.getScreenfull},
 | 
			
		||||
      // 尺寸图标
 | 
			
		||||
      size: ${appStore.getSize},
 | 
			
		||||
      // 多语言图标
 | 
			
		||||
      locale: ${appStore.getLocale},
 | 
			
		||||
      // 标签页
 | 
			
		||||
      tagsView: ${appStore.getTagsView},
 | 
			
		||||
      // 标签页图标
 | 
			
		||||
      getTagsViewIcon: ${appStore.getTagsViewIcon},
 | 
			
		||||
      // logo
 | 
			
		||||
      logo: ${appStore.getLogo},
 | 
			
		||||
      // 菜单手风琴
 | 
			
		||||
      uniqueOpened: ${appStore.getUniqueOpened},
 | 
			
		||||
      // 固定header
 | 
			
		||||
      fixedHeader: ${appStore.getFixedHeader},
 | 
			
		||||
      // 页脚
 | 
			
		||||
      footer: ${appStore.getFooter},
 | 
			
		||||
      // 灰色模式
 | 
			
		||||
      greyMode: ${appStore.getGreyMode},
 | 
			
		||||
      // layout布局
 | 
			
		||||
      layout: '${appStore.getLayout}',
 | 
			
		||||
      // 暗黑模式
 | 
			
		||||
      isDark: ${appStore.getIsDark},
 | 
			
		||||
      // 组件尺寸
 | 
			
		||||
      currentSize: '${appStore.getCurrentSize}',
 | 
			
		||||
      // 主题相关
 | 
			
		||||
      theme: {
 | 
			
		||||
        // 主题色
 | 
			
		||||
        elColorPrimary: '${appStore.getTheme.elColorPrimary}',
 | 
			
		||||
        // 左侧菜单边框颜色
 | 
			
		||||
        leftMenuBorderColor: '${appStore.getTheme.leftMenuBorderColor}',
 | 
			
		||||
        // 左侧菜单背景颜色
 | 
			
		||||
        leftMenuBgColor: '${appStore.getTheme.leftMenuBgColor}',
 | 
			
		||||
        // 左侧菜单浅色背景颜色
 | 
			
		||||
        leftMenuBgLightColor: '${appStore.getTheme.leftMenuBgLightColor}',
 | 
			
		||||
        // 左侧菜单选中背景颜色
 | 
			
		||||
        leftMenuBgActiveColor: '${appStore.getTheme.leftMenuBgActiveColor}',
 | 
			
		||||
        // 左侧菜单收起选中背景颜色
 | 
			
		||||
        leftMenuCollapseBgActiveColor: '${appStore.getTheme.leftMenuCollapseBgActiveColor}',
 | 
			
		||||
        // 左侧菜单字体颜色
 | 
			
		||||
        leftMenuTextColor: '${appStore.getTheme.leftMenuTextColor}',
 | 
			
		||||
        // 左侧菜单选中字体颜色
 | 
			
		||||
        leftMenuTextActiveColor: '${appStore.getTheme.leftMenuTextActiveColor}',
 | 
			
		||||
        // logo字体颜色
 | 
			
		||||
        logoTitleTextColor: '${appStore.getTheme.logoTitleTextColor}',
 | 
			
		||||
        // logo边框颜色
 | 
			
		||||
        logoBorderColor: '${appStore.getTheme.logoBorderColor}',
 | 
			
		||||
        // 头部背景颜色
 | 
			
		||||
        topHeaderBgColor: '${appStore.getTheme.topHeaderBgColor}',
 | 
			
		||||
        // 头部字体颜色
 | 
			
		||||
        topHeaderTextColor: '${appStore.getTheme.topHeaderTextColor}',
 | 
			
		||||
        // 头部悬停颜色
 | 
			
		||||
        topHeaderHoverColor: '${appStore.getTheme.topHeaderHoverColor}',
 | 
			
		||||
        // 头部边框颜色
 | 
			
		||||
        topToolBorderColor: '${appStore.getTheme.topToolBorderColor}'
 | 
			
		||||
      }
 | 
			
		||||
    `
 | 
			
		||||
  })
 | 
			
		||||
  if (!isSupported) {
 | 
			
		||||
    ElMessage.error(t('setting.copyFailed'))
 | 
			
		||||
  } else {
 | 
			
		||||
    await copy()
 | 
			
		||||
    if (unref(copied)) {
 | 
			
		||||
      ElMessage.success(t('setting.copySuccess'))
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// 清空缓存
 | 
			
		||||
const clear = () => {
 | 
			
		||||
  const { wsCache } = useCache()
 | 
			
		||||
  wsCache.delete('layout')
 | 
			
		||||
  wsCache.delete('theme')
 | 
			
		||||
  wsCache.delete('isDark')
 | 
			
		||||
  window.location.reload()
 | 
			
		||||
}
 | 
			
		||||
</script>
 | 
			
		||||
 | 
			
		||||
<template>
 | 
			
		||||
  <div
 | 
			
		||||
    :class="prefixCls"
 | 
			
		||||
    class="fixed top-[45%] right-0 w-40px h-40px text-center leading-40px bg-[var(--el-color-primary)] cursor-pointer"
 | 
			
		||||
    @click="drawer = true"
 | 
			
		||||
  >
 | 
			
		||||
    <Icon icon="ep:setting" color="#fff" />
 | 
			
		||||
  </div>
 | 
			
		||||
 | 
			
		||||
  <ElDrawer v-model="drawer" direction="rtl" size="350px">
 | 
			
		||||
    <template #header>
 | 
			
		||||
      <span class="text-16px font-700">{{ t('setting.projectSetting') }}</span>
 | 
			
		||||
    </template>
 | 
			
		||||
 | 
			
		||||
    <div class="text-center">
 | 
			
		||||
      <!-- 主题 -->
 | 
			
		||||
      <ElDivider>{{ t('setting.theme') }}</ElDivider>
 | 
			
		||||
      <ThemeSwitch />
 | 
			
		||||
 | 
			
		||||
      <!-- 布局 -->
 | 
			
		||||
      <ElDivider>{{ t('setting.layout') }}</ElDivider>
 | 
			
		||||
      <LayoutRadioPicker />
 | 
			
		||||
 | 
			
		||||
      <!-- 系统主题 -->
 | 
			
		||||
      <ElDivider>{{ t('setting.systemTheme') }}</ElDivider>
 | 
			
		||||
      <ColorRadioPicker
 | 
			
		||||
        v-model="systemTheme"
 | 
			
		||||
        :schema="[
 | 
			
		||||
          '#409eff',
 | 
			
		||||
          '#009688',
 | 
			
		||||
          '#536dfe',
 | 
			
		||||
          '#ff5c93',
 | 
			
		||||
          '#ee4f12',
 | 
			
		||||
          '#0096c7',
 | 
			
		||||
          '#9c27b0',
 | 
			
		||||
          '#ff9800'
 | 
			
		||||
        ]"
 | 
			
		||||
        @change="setSystemTheme"
 | 
			
		||||
      />
 | 
			
		||||
 | 
			
		||||
      <!-- 头部主题 -->
 | 
			
		||||
      <ElDivider>{{ t('setting.headerTheme') }}</ElDivider>
 | 
			
		||||
      <ColorRadioPicker
 | 
			
		||||
        v-model="headerTheme"
 | 
			
		||||
        :schema="[
 | 
			
		||||
          '#fff',
 | 
			
		||||
          '#151515',
 | 
			
		||||
          '#5172dc',
 | 
			
		||||
          '#e74c3c',
 | 
			
		||||
          '#24292e',
 | 
			
		||||
          '#394664',
 | 
			
		||||
          '#009688',
 | 
			
		||||
          '#383f45'
 | 
			
		||||
        ]"
 | 
			
		||||
        @change="setHeaderTheme"
 | 
			
		||||
      />
 | 
			
		||||
 | 
			
		||||
      <!-- 菜单主题 -->
 | 
			
		||||
      <template v-if="layout !== 'top'">
 | 
			
		||||
        <ElDivider>{{ t('setting.menuTheme') }}</ElDivider>
 | 
			
		||||
        <ColorRadioPicker
 | 
			
		||||
          v-model="menuTheme"
 | 
			
		||||
          :schema="[
 | 
			
		||||
            '#fff',
 | 
			
		||||
            '#001529',
 | 
			
		||||
            '#212121',
 | 
			
		||||
            '#273352',
 | 
			
		||||
            '#191b24',
 | 
			
		||||
            '#383f45',
 | 
			
		||||
            '#001628',
 | 
			
		||||
            '#344058'
 | 
			
		||||
          ]"
 | 
			
		||||
          @change="setMenuTheme"
 | 
			
		||||
        />
 | 
			
		||||
      </template>
 | 
			
		||||
    </div>
 | 
			
		||||
 | 
			
		||||
    <!-- 界面显示 -->
 | 
			
		||||
    <ElDivider>{{ t('setting.interfaceDisplay') }}</ElDivider>
 | 
			
		||||
    <InterfaceDisplay />
 | 
			
		||||
 | 
			
		||||
    <ElDivider />
 | 
			
		||||
    <div>
 | 
			
		||||
      <ElButton type="primary" class="w-full" @click="copyConfig">{{ t('setting.copy') }}</ElButton>
 | 
			
		||||
    </div>
 | 
			
		||||
    <div class="mt-5px">
 | 
			
		||||
      <ElButton type="danger" class="w-full" @click="clear">
 | 
			
		||||
        {{ t('setting.clearAndReset') }}
 | 
			
		||||
      </ElButton>
 | 
			
		||||
    </div>
 | 
			
		||||
  </ElDrawer>
 | 
			
		||||
</template>
 | 
			
		||||
 | 
			
		||||
<style lang="less" scoped>
 | 
			
		||||
@prefix-cls: ~'@{namespace}-setting';
 | 
			
		||||
 | 
			
		||||
.@{prefix-cls} {
 | 
			
		||||
  border-radius: 6px 0 0 6px;
 | 
			
		||||
}
 | 
			
		||||
</style>
 | 
			
		||||
@@ -0,0 +1,65 @@
 | 
			
		||||
<script setup lang="ts">
 | 
			
		||||
import { PropType, watch, unref, ref } from 'vue'
 | 
			
		||||
import { propTypes } from '@/utils/propTypes'
 | 
			
		||||
import { useDesign } from '@/hooks/web/useDesign'
 | 
			
		||||
 | 
			
		||||
const { getPrefixCls } = useDesign()
 | 
			
		||||
 | 
			
		||||
const prefixCls = getPrefixCls('color-radio-picker')
 | 
			
		||||
 | 
			
		||||
const props = defineProps({
 | 
			
		||||
  schema: {
 | 
			
		||||
    type: Array as PropType<string[]>,
 | 
			
		||||
    default: () => []
 | 
			
		||||
  },
 | 
			
		||||
  modelValue: propTypes.string.def('')
 | 
			
		||||
})
 | 
			
		||||
 | 
			
		||||
const emit = defineEmits(['update:modelValue', 'change'])
 | 
			
		||||
 | 
			
		||||
const colorVal = ref(props.modelValue)
 | 
			
		||||
 | 
			
		||||
watch(
 | 
			
		||||
  () => props.modelValue,
 | 
			
		||||
  (val: string) => {
 | 
			
		||||
    if (val === unref(colorVal)) return
 | 
			
		||||
    colorVal.value = val
 | 
			
		||||
  }
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// 监听
 | 
			
		||||
watch(
 | 
			
		||||
  () => colorVal.value,
 | 
			
		||||
  (val: string) => {
 | 
			
		||||
    emit('update:modelValue', val)
 | 
			
		||||
    emit('change', val)
 | 
			
		||||
  }
 | 
			
		||||
)
 | 
			
		||||
</script>
 | 
			
		||||
 | 
			
		||||
<template>
 | 
			
		||||
  <div :class="prefixCls" class="flex flex-wrap space-x-14px">
 | 
			
		||||
    <span
 | 
			
		||||
      v-for="(item, i) in schema"
 | 
			
		||||
      :key="`radio-${i}`"
 | 
			
		||||
      class="w-20px h-20px cursor-pointer rounded-2px border-solid border-gray-300 border-2px text-center leading-20px mb-5px"
 | 
			
		||||
      :class="{ 'is-active': colorVal === item }"
 | 
			
		||||
      :style="{
 | 
			
		||||
        background: item
 | 
			
		||||
      }"
 | 
			
		||||
      @click="colorVal = item"
 | 
			
		||||
    >
 | 
			
		||||
      <Icon v-if="colorVal === item" color="#fff" icon="ep:check" :size="16" />
 | 
			
		||||
    </span>
 | 
			
		||||
  </div>
 | 
			
		||||
</template>
 | 
			
		||||
 | 
			
		||||
<style lang="less" scoped>
 | 
			
		||||
@prefix-cls: ~'@{namespace}-color-radio-picker';
 | 
			
		||||
 | 
			
		||||
.@{prefix-cls} {
 | 
			
		||||
  .is-active {
 | 
			
		||||
    border-color: var(--el-color-primary);
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
</style>
 | 
			
		||||
@@ -0,0 +1,189 @@
 | 
			
		||||
<script setup lang="ts">
 | 
			
		||||
import { ElSwitch } from 'element-plus'
 | 
			
		||||
import { useI18n } from '@/hooks/web/useI18n'
 | 
			
		||||
import { useAppStore } from '@/store/modules/app'
 | 
			
		||||
import { computed, ref, watch } from 'vue'
 | 
			
		||||
import { setCssVar } from '@/utils'
 | 
			
		||||
import { useDesign } from '@/hooks/web/useDesign'
 | 
			
		||||
 | 
			
		||||
const { getPrefixCls } = useDesign()
 | 
			
		||||
 | 
			
		||||
const prefixCls = getPrefixCls('interface-display')
 | 
			
		||||
 | 
			
		||||
const appStore = useAppStore()
 | 
			
		||||
 | 
			
		||||
const { t } = useI18n()
 | 
			
		||||
 | 
			
		||||
// 面包屑
 | 
			
		||||
const breadcrumb = ref(appStore.getBreadcrumb)
 | 
			
		||||
 | 
			
		||||
const breadcrumbChange = (show: boolean) => {
 | 
			
		||||
  appStore.setBreadcrumb(show)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// 面包屑图标
 | 
			
		||||
const breadcrumbIcon = ref(appStore.getBreadcrumbIcon)
 | 
			
		||||
 | 
			
		||||
const breadcrumbIconChange = (show: boolean) => {
 | 
			
		||||
  appStore.setBreadcrumbIcon(show)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// 折叠图标
 | 
			
		||||
const hamburger = ref(appStore.getHamburger)
 | 
			
		||||
 | 
			
		||||
const hamburgerChange = (show: boolean) => {
 | 
			
		||||
  appStore.setHamburger(show)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// 全屏图标
 | 
			
		||||
const screenfull = ref(appStore.getScreenfull)
 | 
			
		||||
 | 
			
		||||
const screenfullChange = (show: boolean) => {
 | 
			
		||||
  appStore.setScreenfull(show)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// 尺寸图标
 | 
			
		||||
const size = ref(appStore.getSize)
 | 
			
		||||
 | 
			
		||||
const sizeChange = (show: boolean) => {
 | 
			
		||||
  appStore.setSize(show)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// 多语言图标
 | 
			
		||||
const locale = ref(appStore.getLocale)
 | 
			
		||||
 | 
			
		||||
const localeChange = (show: boolean) => {
 | 
			
		||||
  appStore.setLocale(show)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// 标签页
 | 
			
		||||
const tagsView = ref(appStore.getTagsView)
 | 
			
		||||
 | 
			
		||||
const tagsViewChange = (show: boolean) => {
 | 
			
		||||
  // 切换标签栏显示时,同步切换标签栏的高度
 | 
			
		||||
  setCssVar('--tags-view-height', show ? '35px' : '0px')
 | 
			
		||||
  appStore.setTagsView(show)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// 标签页图标
 | 
			
		||||
const tagsViewIcon = ref(appStore.getTagsViewIcon)
 | 
			
		||||
 | 
			
		||||
const tagsViewIconChange = (show: boolean) => {
 | 
			
		||||
  appStore.setTagsViewIcon(show)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// logo
 | 
			
		||||
const logo = ref(appStore.getLogo)
 | 
			
		||||
 | 
			
		||||
const logoChange = (show: boolean) => {
 | 
			
		||||
  appStore.setLogo(show)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// 菜单手风琴
 | 
			
		||||
const uniqueOpened = ref(appStore.getUniqueOpened)
 | 
			
		||||
 | 
			
		||||
const uniqueOpenedChange = (uniqueOpened: boolean) => {
 | 
			
		||||
  appStore.setUniqueOpened(uniqueOpened)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// 固定头部
 | 
			
		||||
const fixedHeader = ref(appStore.getFixedHeader)
 | 
			
		||||
 | 
			
		||||
const fixedHeaderChange = (show: boolean) => {
 | 
			
		||||
  appStore.setFixedHeader(show)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// 页脚
 | 
			
		||||
const footer = ref(appStore.getFooter)
 | 
			
		||||
 | 
			
		||||
const footerChange = (show: boolean) => {
 | 
			
		||||
  appStore.setFooter(show)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// 灰色模式
 | 
			
		||||
const greyMode = ref(appStore.getGreyMode)
 | 
			
		||||
 | 
			
		||||
const greyModeChange = (show: boolean) => {
 | 
			
		||||
  appStore.setGreyMode(show)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
const layout = computed(() => appStore.getLayout)
 | 
			
		||||
 | 
			
		||||
watch(
 | 
			
		||||
  () => layout.value,
 | 
			
		||||
  (n) => {
 | 
			
		||||
    if (n === 'top') {
 | 
			
		||||
      appStore.setCollapse(false)
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
)
 | 
			
		||||
</script>
 | 
			
		||||
 | 
			
		||||
<template>
 | 
			
		||||
  <div :class="prefixCls">
 | 
			
		||||
    <div class="flex justify-between items-center">
 | 
			
		||||
      <span class="text-14px">{{ t('setting.breadcrumb') }}</span>
 | 
			
		||||
      <ElSwitch v-model="breadcrumb" @change="breadcrumbChange" />
 | 
			
		||||
    </div>
 | 
			
		||||
 | 
			
		||||
    <div class="flex justify-between items-center">
 | 
			
		||||
      <span class="text-14px">{{ t('setting.breadcrumbIcon') }}</span>
 | 
			
		||||
      <ElSwitch v-model="breadcrumbIcon" @change="breadcrumbIconChange" />
 | 
			
		||||
    </div>
 | 
			
		||||
 | 
			
		||||
    <div class="flex justify-between items-center">
 | 
			
		||||
      <span class="text-14px">{{ t('setting.hamburgerIcon') }}</span>
 | 
			
		||||
      <ElSwitch v-model="hamburger" @change="hamburgerChange" />
 | 
			
		||||
    </div>
 | 
			
		||||
 | 
			
		||||
    <div class="flex justify-between items-center">
 | 
			
		||||
      <span class="text-14px">{{ t('setting.screenfullIcon') }}</span>
 | 
			
		||||
      <ElSwitch v-model="screenfull" @change="screenfullChange" />
 | 
			
		||||
    </div>
 | 
			
		||||
 | 
			
		||||
    <div class="flex justify-between items-center">
 | 
			
		||||
      <span class="text-14px">{{ t('setting.sizeIcon') }}</span>
 | 
			
		||||
      <ElSwitch v-model="size" @change="sizeChange" />
 | 
			
		||||
    </div>
 | 
			
		||||
 | 
			
		||||
    <div class="flex justify-between items-center">
 | 
			
		||||
      <span class="text-14px">{{ t('setting.localeIcon') }}</span>
 | 
			
		||||
      <ElSwitch v-model="locale" @change="localeChange" />
 | 
			
		||||
    </div>
 | 
			
		||||
 | 
			
		||||
    <div class="flex justify-between items-center">
 | 
			
		||||
      <span class="text-14px">{{ t('setting.tagsView') }}</span>
 | 
			
		||||
      <ElSwitch v-model="tagsView" @change="tagsViewChange" />
 | 
			
		||||
    </div>
 | 
			
		||||
 | 
			
		||||
    <div class="flex justify-between items-center">
 | 
			
		||||
      <span class="text-14px">{{ t('setting.tagsViewIcon') }}</span>
 | 
			
		||||
      <ElSwitch v-model="tagsViewIcon" @change="tagsViewIconChange" />
 | 
			
		||||
    </div>
 | 
			
		||||
 | 
			
		||||
    <div class="flex justify-between items-center">
 | 
			
		||||
      <span class="text-14px">{{ t('setting.logo') }}</span>
 | 
			
		||||
      <ElSwitch v-model="logo" @change="logoChange" />
 | 
			
		||||
    </div>
 | 
			
		||||
 | 
			
		||||
    <div class="flex justify-between items-center">
 | 
			
		||||
      <span class="text-14px">{{ t('setting.uniqueOpened') }}</span>
 | 
			
		||||
      <ElSwitch v-model="uniqueOpened" @change="uniqueOpenedChange" />
 | 
			
		||||
    </div>
 | 
			
		||||
 | 
			
		||||
    <div class="flex justify-between items-center">
 | 
			
		||||
      <span class="text-14px">{{ t('setting.fixedHeader') }}</span>
 | 
			
		||||
      <ElSwitch v-model="fixedHeader" @change="fixedHeaderChange" />
 | 
			
		||||
    </div>
 | 
			
		||||
 | 
			
		||||
    <div class="flex justify-between items-center">
 | 
			
		||||
      <span class="text-14px">{{ t('setting.footer') }}</span>
 | 
			
		||||
      <ElSwitch v-model="footer" @change="footerChange" />
 | 
			
		||||
    </div>
 | 
			
		||||
 | 
			
		||||
    <div class="flex justify-between items-center">
 | 
			
		||||
      <span class="text-14px">{{ t('setting.greyMode') }}</span>
 | 
			
		||||
      <ElSwitch v-model="greyMode" @change="greyModeChange" />
 | 
			
		||||
    </div>
 | 
			
		||||
  </div>
 | 
			
		||||
</template>
 | 
			
		||||
@@ -0,0 +1,171 @@
 | 
			
		||||
<script setup lang="ts">
 | 
			
		||||
import { useAppStore } from '@/store/modules/app'
 | 
			
		||||
import { computed } from 'vue'
 | 
			
		||||
import { useDesign } from '@/hooks/web/useDesign'
 | 
			
		||||
 | 
			
		||||
const { getPrefixCls } = useDesign()
 | 
			
		||||
 | 
			
		||||
const prefixCls = getPrefixCls('layout-radio-picker')
 | 
			
		||||
 | 
			
		||||
const appStore = useAppStore()
 | 
			
		||||
 | 
			
		||||
const layout = computed(() => appStore.getLayout)
 | 
			
		||||
</script>
 | 
			
		||||
 | 
			
		||||
<template>
 | 
			
		||||
  <div :class="prefixCls" class="flex flex-wrap space-x-14px">
 | 
			
		||||
    <div
 | 
			
		||||
      :class="[
 | 
			
		||||
        `${prefixCls}__classic`,
 | 
			
		||||
        'relative w-56px h-48px cursor-pointer bg-gray-300',
 | 
			
		||||
        {
 | 
			
		||||
          'is-acitve': layout === 'classic'
 | 
			
		||||
        }
 | 
			
		||||
      ]"
 | 
			
		||||
      @click="appStore.setLayout('classic')"
 | 
			
		||||
    ></div>
 | 
			
		||||
    <div
 | 
			
		||||
      :class="[
 | 
			
		||||
        `${prefixCls}__top-left`,
 | 
			
		||||
        'relative w-56px h-48px cursor-pointer bg-gray-300',
 | 
			
		||||
        {
 | 
			
		||||
          'is-acitve': layout === 'topLeft'
 | 
			
		||||
        }
 | 
			
		||||
      ]"
 | 
			
		||||
      @click="appStore.setLayout('topLeft')"
 | 
			
		||||
    ></div>
 | 
			
		||||
    <div
 | 
			
		||||
      :class="[
 | 
			
		||||
        `${prefixCls}__top`,
 | 
			
		||||
        'relative w-56px h-48px cursor-pointer bg-gray-300',
 | 
			
		||||
        {
 | 
			
		||||
          'is-acitve': layout === 'top'
 | 
			
		||||
        }
 | 
			
		||||
      ]"
 | 
			
		||||
      @click="appStore.setLayout('top')"
 | 
			
		||||
    ></div>
 | 
			
		||||
    <div
 | 
			
		||||
      :class="[
 | 
			
		||||
        `${prefixCls}__cut-menu`,
 | 
			
		||||
        'relative w-56px h-48px cursor-pointer bg-gray-300',
 | 
			
		||||
        {
 | 
			
		||||
          'is-acitve': layout === 'cutMenu'
 | 
			
		||||
        }
 | 
			
		||||
      ]"
 | 
			
		||||
      @click="appStore.setLayout('cutMenu')"
 | 
			
		||||
    >
 | 
			
		||||
      <div class="absolute h-full w-[33%] top-0 left-[10%] bg-gray-200"></div>
 | 
			
		||||
    </div>
 | 
			
		||||
  </div>
 | 
			
		||||
</template>
 | 
			
		||||
 | 
			
		||||
<style lang="less" scoped>
 | 
			
		||||
@prefix-cls: ~'@{namespace}-layout-radio-picker';
 | 
			
		||||
 | 
			
		||||
.@{prefix-cls} {
 | 
			
		||||
  &__classic {
 | 
			
		||||
    border: 2px solid #e5e7eb;
 | 
			
		||||
    border-radius: 4px;
 | 
			
		||||
 | 
			
		||||
    &:before {
 | 
			
		||||
      position: absolute;
 | 
			
		||||
      top: 0;
 | 
			
		||||
      left: 0;
 | 
			
		||||
      z-index: 1;
 | 
			
		||||
      width: 33%;
 | 
			
		||||
      height: 100%;
 | 
			
		||||
      background-color: #273352;
 | 
			
		||||
      border-radius: 4px 0 0 4px;
 | 
			
		||||
      content: '';
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    &:after {
 | 
			
		||||
      position: absolute;
 | 
			
		||||
      top: 0;
 | 
			
		||||
      left: 0;
 | 
			
		||||
      width: 100%;
 | 
			
		||||
      height: 25%;
 | 
			
		||||
      background-color: #fff;
 | 
			
		||||
      border-radius: 4px 4px 0 4px;
 | 
			
		||||
      content: '';
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  &__top-left {
 | 
			
		||||
    border: 2px solid #e5e7eb;
 | 
			
		||||
    border-radius: 4px;
 | 
			
		||||
 | 
			
		||||
    &:before {
 | 
			
		||||
      position: absolute;
 | 
			
		||||
      top: 0;
 | 
			
		||||
      left: 0;
 | 
			
		||||
      z-index: 1;
 | 
			
		||||
      width: 100%;
 | 
			
		||||
      height: 33%;
 | 
			
		||||
      background-color: #273352;
 | 
			
		||||
      border-radius: 4px 4px 0 0;
 | 
			
		||||
      content: '';
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    &:after {
 | 
			
		||||
      position: absolute;
 | 
			
		||||
      top: 0;
 | 
			
		||||
      left: 0;
 | 
			
		||||
      width: 33%;
 | 
			
		||||
      height: 100%;
 | 
			
		||||
      background-color: #fff;
 | 
			
		||||
      border-radius: 4px 0 0 4px;
 | 
			
		||||
      content: '';
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  &__top {
 | 
			
		||||
    border: 2px solid #e5e7eb;
 | 
			
		||||
    border-radius: 4px;
 | 
			
		||||
 | 
			
		||||
    &:before {
 | 
			
		||||
      position: absolute;
 | 
			
		||||
      top: 0;
 | 
			
		||||
      left: 0;
 | 
			
		||||
      z-index: 1;
 | 
			
		||||
      width: 100%;
 | 
			
		||||
      height: 33%;
 | 
			
		||||
      background-color: #273352;
 | 
			
		||||
      border-radius: 4px 4px 0 0;
 | 
			
		||||
      content: '';
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  &__cut-menu {
 | 
			
		||||
    border: 2px solid #e5e7eb;
 | 
			
		||||
    border-radius: 4px;
 | 
			
		||||
 | 
			
		||||
    &:before {
 | 
			
		||||
      position: absolute;
 | 
			
		||||
      top: 0;
 | 
			
		||||
      left: 0;
 | 
			
		||||
      z-index: 1;
 | 
			
		||||
      width: 100%;
 | 
			
		||||
      height: 33%;
 | 
			
		||||
      background-color: #273352;
 | 
			
		||||
      border-radius: 4px 4px 0 0;
 | 
			
		||||
      content: '';
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    &:after {
 | 
			
		||||
      position: absolute;
 | 
			
		||||
      top: 0;
 | 
			
		||||
      left: 0;
 | 
			
		||||
      width: 10%;
 | 
			
		||||
      height: 100%;
 | 
			
		||||
      background-color: #fff;
 | 
			
		||||
      border-radius: 4px 0 0 4px;
 | 
			
		||||
      content: '';
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  .is-acitve {
 | 
			
		||||
    border-color: var(--el-color-primary);
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
</style>
 | 
			
		||||
		Reference in New Issue
	
	Block a user