forked from opentiny/tiny-vue
feat(sites): add theme route (#1478)
This commit is contained in:
parent
defd25a462
commit
90c2eb02ba
|
@ -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
|
||||
}
|
||||
|
|
|
@ -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
|
||||
})
|
||||
|
|
|
@ -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` }
|
||||
}
|
||||
}
|
||||
]
|
||||
|
|
|
@ -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]
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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)
|
||||
|
||||
// 单demo处理,如果有hash,取hash的demo, 没有hash, 取第1项
|
||||
|
|
|
@ -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: 目前mf只有Options写法,后续再放开compositon
|
||||
const url = `${import.meta.env.VITE_PLAYGROUND_URL}?cmpId=${cmpId}&fileName=${
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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-')) {
|
||||
|
|
Loading…
Reference in New Issue