feat(sites): add theme route (#1478)

This commit is contained in:
gimmyhehe 2024-03-11 09:15:04 +08:00 committed by GitHub
parent defd25a462
commit 90c2eb02ba
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
8 changed files with 110 additions and 82 deletions

View File

@ -1,6 +1,6 @@
<template>
<div class="hp100 of-hidden">
<tiny-config-provider :design="designConfig">
<tiny-config-provider :design="designConfig" :key="currentThemeKey">
<router-view />
<tiny-modal :show-header="false" :show-footer="false" v-model="modalSHow" width="1400px" height="900px" resize>
<tiny-icon-close class="close-icon" @click="modalSHow = false"></tiny-icon-close>
@ -41,7 +41,7 @@ export default defineComponent({
})
common.renderHeader()
})
const { designConfig } = useTheme()
const { designConfig, currentThemeKey } = useTheme()
provide('showPreview', (url) => {
previewUrl.value = url
@ -50,6 +50,7 @@ export default defineComponent({
return {
appData,
designConfig,
currentThemeKey,
previewUrl,
modalSHow
}

View File

@ -8,3 +8,30 @@ export const LANG_PATH_MAP = {
[ZH_CN_LANG]: 'zh-CN',
[EN_US_LANG]: 'en-US'
}
export const CURRENT_THEME_KEY = 'tiny-current-theme'
// 主题
export const DEFAULT_THEME = 'tiny-default-theme'
export const AURORA_THEME = 'tiny-aurora-theme'
export const SMB_THEME = 'tiny-smb-theme'
export const INFINITY_THEME = 'tiny-infinity-theme'
// 主题对应路由参数映射表
export const THEME_ROUTE_MAP = {
[DEFAULT_THEME]: 'os-theme',
[AURORA_THEME]: 'aurora-theme',
[SMB_THEME]: 'smb-theme',
[INFINITY_THEME]: 'infinity-theme'
}
/**
* @description key
* @param map
* @param val
* @returns key
*/
export const getKeyByValue = (map, val) =>
Object.keys(map).find((key) => {
return map[key] === val
})

View File

@ -1,6 +1,6 @@
import { createRouter, createWebHistory } from 'vue-router'
import Layout from '@/views/layout/layout.vue'
import { LANG_KEY, LANG_PATH_MAP, ZH_CN_LANG } from './const'
import { LANG_KEY, LANG_PATH_MAP, ZH_CN_LANG, CURRENT_THEME_KEY, THEME_ROUTE_MAP, DEFAULT_THEME } from './const'
import { $local } from './tools/storage'
const Components = () => import('@/views/components/components.vue')
@ -12,7 +12,7 @@ const context = import.meta.env.VITE_CONTEXT
let routes = [
// 组件总览
{
path: `${context}:all?/:lang/overview`,
path: `${context}:all?/:lang/:theme/overview`,
component: Layout,
name: 'overview',
children: [{ name: 'Overview', path: '', component: Overview, meta: { title: '组件总览 | TinyVue' } }]
@ -37,7 +37,9 @@ let routes = [
redirect: () => {
const lang = $local[LANG_KEY]
const langPath = LANG_PATH_MAP[lang] || LANG_PATH_MAP[ZH_CN_LANG]
return { path: `${context}${langPath}/overview` }
const themeKey = localStorage.getItem(CURRENT_THEME_KEY)
const theme = THEME_ROUTE_MAP[themeKey] || THEME_ROUTE_MAP[DEFAULT_THEME]
return { path: `${context}${langPath}/${theme}/overview` }
}
}
]

View File

@ -2,87 +2,97 @@ import { watch, computed } from 'vue'
import TinyThemeTool from '@opentiny/vue-theme/theme-tool'
import { tinyAuroraTheme, tinySmbTheme, tinyInfinityTheme } from '@opentiny/vue-theme/theme'
import { hooks } from '@opentiny/vue-common'
import { Notify } from '@opentiny/vue'
import designSmbConfig from '@opentiny/vue-design-smb'
import designAuroraConfig from '@opentiny/vue-design-aurora'
import designSaasConfig from '@opentiny/vue-design-saas'
import { router } from '@/router'
import { appData } from './appData'
import {
THEME_ROUTE_MAP,
CURRENT_THEME_KEY,
DEFAULT_THEME,
AURORA_THEME,
SMB_THEME,
INFINITY_THEME,
getKeyByValue
} from '../const'
const CURRENT_THEME_KEY = 'tiny-current-theme'
const themeMap = {
[DEFAULT_THEME]: null,
[AURORA_THEME]: tinyAuroraTheme,
[SMB_THEME]: tinySmbTheme,
[INFINITY_THEME]: tinyInfinityTheme
}
const isEn = appData.lang === 'enUS'
const themeData = [
{ value: 'tiny-default-theme', label: isEn ? 'Default Theme' : '默认主题' },
{ value: 'tiny-infinity-theme', label: isEn ? 'Infinity Theme' : '无限主题' },
{ value: 'tiny-aurora-theme', label: isEn ? 'Aurora Theme' : 'Aurora 主题' },
{ value: 'tiny-smb-theme', label: isEn ? 'SMB Theme' : 'SMB 主题' }
{ value: [DEFAULT_THEME], label: isEn ? 'Default Theme' : '默认主题' },
{ value: [INFINITY_THEME], label: isEn ? 'Infinity Theme' : '无限主题' },
{ value: [AURORA_THEME], label: isEn ? 'Aurora Theme' : 'Aurora 主题' },
{ value: [SMB_THEME], label: isEn ? 'SMB Theme' : 'SMB 主题' }
]
const designConfigMap = {
'tiny-default-theme': {},
'tiny-infinity-theme': {},
'tiny-aurora-theme': designAuroraConfig,
'tiny-smb-theme': designSmbConfig
}
let isShowTip = false
function showTip() {
Notify({
type: 'info',
title: '请注意',
message: '主题切换成功,如有部分主题样式不生效,请尝试手动刷新页面即可',
position: 'top-right',
duration: 3000,
verticalOffset: 200
})
isShowTip = true
[DEFAULT_THEME]: {},
[INFINITY_THEME]: {},
[AURORA_THEME]: designAuroraConfig,
[SMB_THEME]: designSmbConfig
}
const theme = new TinyThemeTool()
const lastThemeKey = localStorage.getItem(CURRENT_THEME_KEY)
const currThemeLabel = hooks.ref(lastThemeKey || 'tiny-default-theme')
const defaultThemeKey = DEFAULT_THEME
const currentThemeKey = hooks.ref(defaultThemeKey)
watch(
() => currentThemeKey.value,
(newVal) => {
localStorage.setItem(CURRENT_THEME_KEY, newVal)
theme.changeTheme(themeMap[newVal])
}
)
const designConfig = computed(() => {
if (import.meta.env.VITE_TINY_THEME === 'saas') {
return designSaasConfig
}
return designConfigMap[currThemeLabel.value]
return designConfigMap[currentThemeKey.value]
})
const THEME_MAP = {
'tiny-aurora-theme': tinyAuroraTheme,
'tiny-smb-theme': tinySmbTheme,
'tiny-infinity-theme': tinyInfinityTheme
}
const changeTheme = (themeValue) => {
currThemeLabel.value = themeValue
}
watch(
() => currThemeLabel.value,
(newVal) => {
localStorage.setItem(CURRENT_THEME_KEY, newVal)
theme.changeTheme(THEME_MAP[newVal])
// 若部分主题样式切换不生效,第一次则提示用户需要手动刷新
if (!isShowTip) {
showTip()
const changeTheme = (themeKey) => {
router.push({
params: {
theme: THEME_ROUTE_MAP[themeKey]
}
}
)
// 切换上次缓存的主题
if (THEME_MAP[lastThemeKey]) {
theme.changeTheme(THEME_MAP[lastThemeKey])
})
}
// 返回拷贝,防止原始数据被修改
const getThemeData = () => JSON.parse(JSON.stringify(themeData))
let initWatchRoute = false
const watchRoute = () => {
if (initWatchRoute) {
return
}
initWatchRoute = true
watch(
() => router.currentRoute.value.params.theme,
(val) => {
const themeKey = getKeyByValue(THEME_ROUTE_MAP, val)
currentThemeKey.value = themeKey || defaultThemeKey
}
)
}
export default function useTheme() {
watchRoute()
return {
getThemeData,
changeTheme,
currThemeLabel,
designConfig
currentThemeKey,
designConfig,
defaultTheme: THEME_ROUTE_MAP[defaultThemeKey]
}
}

View File

@ -145,7 +145,7 @@ import { i18nByKey, getWord, $clone, fetchDemosFile, useApiMode, useTemplateMode
import demo from '@/views/components/demo'
import { router } from '@/router.js'
import { Collapse, CollapseItem } from '@opentiny/vue'
import { faqMdConfig, staticDemoPath, getWebdocPath } from './cmpConfig'
import { faqMdConfig, getWebdocPath } from './cmpConfig'
import AsyncHighlight from './async-highlight.vue'
import VersionTip from './VersionTip.vue'
@ -313,21 +313,6 @@ export default defineComponent({
state.currJson.types = apiJson.types
}
if (state.cmpId?.startsWith('grid-')) {
fetchDemosFile(`${staticDemoPath}/grid/webdoc/grid.js`).then((data) => {
// eslint-disable-next-line no-eval
const gridJson = eval('(' + data.slice(15) + ')')
state.currJson.apis = gridJson.apis
state.currJson.types = gridJson.types
})
} else if (state.cmpId?.startsWith('chart-')) {
fetchDemosFile(`${staticDemoPath}/chart/webdoc/chart.js`).then((data) => {
// eslint-disable-next-line no-eval
const chartJson = eval('(' + data.slice(15) + ')')
state.currJson.apis = chartJson.apis
})
}
let hash = router.currentRoute.value.hash?.slice(1)
// demohash,hashdemo, hash, 1

View File

@ -84,7 +84,7 @@ export default defineComponent({
},
setup(props) {
const { templateModeState } = useTemplateMode()
const { currThemeLabel } = useTheme()
const { currentThemeKey } = useTheme()
const isMobileFirst = computed(() => {
return templateModeState.mode === 'mobile-first'
})
@ -179,7 +179,7 @@ export default defineComponent({
},
openPlayground(demo, open = true) {
const cmpId = router.currentRoute.value.params.cmpId
const tinyTheme = templateModeState.isSaas ? 'saas' : currThemeLabel.value.split('-')[1]
const tinyTheme = templateModeState.isSaas ? 'saas' : currentThemeKey.value.split('-')[1]
const openModeQuery = open ? '' : '&openMode=preview'
// TODO: mfOptionscompositon
const url = `${import.meta.env.VITE_PLAYGROUND_URL}?cmpId=${cmpId}&fileName=${

View File

@ -19,7 +19,7 @@
v-for="(item, index) in themeData"
:key="index"
@click="themeItemClick(item)"
:class="{ 'is-actived': item.value === currThemeLabel }"
:class="{ 'is-actived': item.value === currentThemeKey }"
>
{{ item.label }}
</tiny-dropdown-item>
@ -128,7 +128,7 @@ export default defineComponent({
},
props: [],
setup() {
const { getThemeData, changeTheme, currThemeLabel } = useTheme()
const { getThemeData, changeTheme, currentThemeKey, defaultTheme } = useTheme()
const { apiModeState, apiModeFn } = useApiMode()
const { templateModeState } = useTemplateMode()
let state = reactive({
@ -142,9 +142,9 @@ export default defineComponent({
})
const lang = getWord('zh-CN', 'en-US')
const allPathParam = useRoute().params.all
const { all: allPathParam, theme = defaultTheme } = useRoute().params
const allPath = allPathParam ? allPathParam + '/' : ''
const getTo = (route, key) => `${import.meta.env.VITE_CONTEXT}${allPath}${lang}/os-theme/${route}${key}`
const getTo = (route, key) => `${import.meta.env.VITE_CONTEXT}${allPath}${lang}/${theme}/${route}${key}`
const changeLanguage = () => {
appFn.toggleLang()
@ -211,7 +211,7 @@ export default defineComponent({
collapseChange,
themeData: getThemeData(),
themeItemClick,
currThemeLabel,
currentThemeKey,
themeSvg,
changeLanguage,
apiModeState,

View File

@ -68,6 +68,7 @@ import TinyInput from '@opentiny/vue-input'
import noDataSvg from '@/assets/images/no-data.svg?url'
import searchSvg from '@/assets/images/search.svg?url'
import { getWord, i18nByKey, isZhCn, pubUrl } from '@/tools'
import useTheme from '@/tools/useTheme'
export default defineComponent({
name: 'Overview',
@ -94,7 +95,7 @@ export default defineComponent({
}
}
function searchResultFn(event) {
const value = event.target.value
const value = event
const trimValue = value.replaceAll(' ', '').toLowerCase()
const currentValue = trimValue
const reg = new RegExp(currentValue, 'ig')
@ -116,11 +117,13 @@ export default defineComponent({
state.searchMenus = searchMenus
}
const lang = getWord('zh-CN', 'en-US')
const allPathParam = useRoute().params.all
const { defaultThemeKey } = useTheme()
const { all: allPathParam, theme = defaultThemeKey } = useRoute().params
const allPath = allPathParam ? allPathParam + '/' : ''
let fn = {
searchHandler: debounce(searchResultFn, 300),
getTo: (key) => `${import.meta.env.VITE_CONTEXT}${allPath}${lang}/os-theme/components/${key}`,
getTo: (key) => `${import.meta.env.VITE_CONTEXT}${allPath}${lang}/${theme}/components/${key}`,
getSvg: (key) => {
// 使
if (key.startsWith('grid-')) {