feat(hooks): Add useIntro hook
feat: Add guide demo
This commit is contained in:
3
src/components/ContentWrap/index.ts
Normal file
3
src/components/ContentWrap/index.ts
Normal file
@@ -0,0 +1,3 @@
|
||||
import ContentWrap from './src/ContentWrap.vue'
|
||||
|
||||
export { ContentWrap }
|
||||
35
src/components/ContentWrap/src/ContentWrap.vue
Normal file
35
src/components/ContentWrap/src/ContentWrap.vue
Normal file
@@ -0,0 +1,35 @@
|
||||
<script setup lang="ts">
|
||||
import { ElCard, ElTooltip } from 'element-plus'
|
||||
import { propTypes } from '@/utils/propTypes'
|
||||
import { useDesign } from '@/hooks/web/useDesign'
|
||||
|
||||
const { getPrefixCls } = useDesign()
|
||||
|
||||
const prefixCls = getPrefixCls('content-wrap')
|
||||
|
||||
defineProps({
|
||||
title: propTypes.string.def(''),
|
||||
message: propTypes.string.def('')
|
||||
})
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<ElCard :class="prefixCls" shadow="never">
|
||||
<template v-if="title" #header>
|
||||
<div class="flex items-center">
|
||||
{{ title }}
|
||||
<ElTooltip v-if="message" effect="dark" placement="right">
|
||||
<template #content>
|
||||
<div class="max-w-200px">{{ message }}</div>
|
||||
</template>
|
||||
<Icon class="ml-5px" icon="bi:question-circle-fill" :size="14" />
|
||||
</ElTooltip>
|
||||
</div>
|
||||
</template>
|
||||
<div>
|
||||
<slot></slot>
|
||||
</div>
|
||||
</ElCard>
|
||||
</template>
|
||||
|
||||
<style lang="less" scoped></style>
|
||||
@@ -70,6 +70,7 @@ export default defineComponent({
|
||||
|
||||
return () => (
|
||||
<div
|
||||
id={prefixCls}
|
||||
class={[
|
||||
`${prefixCls} ${prefixCls}__${unref(menuMode)}`,
|
||||
'h-[100%] overflow-hidden z-100 flex-col bg-[var(--left-menu-bg-color)]',
|
||||
|
||||
@@ -12,7 +12,7 @@ import { cloneDeep } from 'lodash-es'
|
||||
import { filterMenusPath, initTabMap, tabPathMap } from './helper'
|
||||
import { useDesign } from '@/hooks/web/useDesign'
|
||||
|
||||
const { getPrefixCls } = useDesign()
|
||||
const { getPrefixCls, variables } = useDesign()
|
||||
|
||||
const prefixCls = getPrefixCls('tab-menu')
|
||||
|
||||
@@ -106,6 +106,7 @@ export default defineComponent({
|
||||
|
||||
return () => (
|
||||
<div
|
||||
id={`${variables.namespace}-menu`}
|
||||
class={[
|
||||
prefixCls,
|
||||
'relative bg-[var(--left-menu-bg-color)] top-1px',
|
||||
|
||||
@@ -148,7 +148,7 @@ watch(
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div :class="prefixCls" class="h-[var(--tags-view-height)] flex w-full relative">
|
||||
<div :id="prefixCls" :class="prefixCls" class="h-[var(--tags-view-height)] flex w-full relative">
|
||||
<span
|
||||
:class="`${prefixCls}__tool`"
|
||||
class="w-[var(--tags-view-height)] h-[var(--tags-view-height)] text-center leading-[var(--tags-view-height)] cursor-pointer"
|
||||
|
||||
41
src/hooks/web/useIntro.ts
Normal file
41
src/hooks/web/useIntro.ts
Normal file
@@ -0,0 +1,41 @@
|
||||
import introJs from 'intro.js'
|
||||
import { IntroJs, Step, Options } from 'intro.js'
|
||||
import 'intro.js/introjs.css'
|
||||
import { useI18n } from '@/hooks/web/useI18n'
|
||||
import { useDesign } from '@/hooks/web/useDesign'
|
||||
|
||||
export const useIntro = (setps?: Step[], options?: Options) => {
|
||||
const { t } = useI18n()
|
||||
|
||||
const { variables } = useDesign()
|
||||
|
||||
const defaultSetps: Step[] = setps || [
|
||||
{
|
||||
element: `#${variables.namespace}-menu`,
|
||||
title: t('common.menu'),
|
||||
intro: t('common.menuDes'),
|
||||
position: 'right'
|
||||
},
|
||||
{
|
||||
element: `#${variables.namespace}-tags-view`,
|
||||
title: t('common.tagsView'),
|
||||
intro: t('common.tagsViewDes'),
|
||||
position: 'bottom'
|
||||
}
|
||||
]
|
||||
|
||||
const defaultOptions: Options = options || {
|
||||
prevLabel: t('common.prevLabel'),
|
||||
nextLabel: t('common.nextLabel'),
|
||||
skipLabel: t('common.skipLabel'),
|
||||
doneLabel: t('common.doneLabel')
|
||||
}
|
||||
|
||||
const introRef: IntroJs = introJs()
|
||||
|
||||
introRef.addSteps(defaultSetps).setOptions(defaultOptions)
|
||||
|
||||
return {
|
||||
introRef
|
||||
}
|
||||
}
|
||||
@@ -11,7 +11,7 @@ import { useDesign } from '@/hooks/web/useDesign'
|
||||
|
||||
const { getPrefixCls } = useDesign()
|
||||
|
||||
const prefixCls = getPrefixCls('layout-content')
|
||||
const prefixCls = getPrefixCls('layout')
|
||||
|
||||
const appStore = useAppStore()
|
||||
|
||||
@@ -54,7 +54,7 @@ export const useRenderLayout = () => {
|
||||
</div>
|
||||
<div
|
||||
class={[
|
||||
prefixCls,
|
||||
`${prefixCls}-content`,
|
||||
'absolute top-0 h-[100%]',
|
||||
{
|
||||
'w-[calc(100%-var(--left-menu-min-width))] left-[var(--left-menu-min-width)]':
|
||||
@@ -69,7 +69,7 @@ export const useRenderLayout = () => {
|
||||
<ElScrollbar
|
||||
v-loading={pageLoading.value}
|
||||
class={[
|
||||
`${prefixCls}-scrollbar`,
|
||||
`${prefixCls}-content-scrollbar`,
|
||||
{
|
||||
'!h-[calc(100%-var(--top-tool-height)-var(--tags-view-height))] mt-[calc(var(--top-tool-height)+var(--tags-view-height))]':
|
||||
fixedHeader.value
|
||||
@@ -115,7 +115,7 @@ export const useRenderLayout = () => {
|
||||
<Menu class="!h-full"></Menu>
|
||||
<div
|
||||
class={[
|
||||
prefixCls,
|
||||
`${prefixCls}-content`,
|
||||
'h-[100%]',
|
||||
{
|
||||
'w-[calc(100%-var(--left-menu-min-width))] left-[var(--left-menu-min-width)]':
|
||||
@@ -129,7 +129,7 @@ export const useRenderLayout = () => {
|
||||
<ElScrollbar
|
||||
v-loading={pageLoading.value}
|
||||
class={[
|
||||
`${prefixCls}-scrollbar`,
|
||||
`${prefixCls}-content-scrollbar`,
|
||||
{
|
||||
'!h-[calc(100%-var(--tags-view-height))] mt-[calc(var(--tags-view-height))]':
|
||||
fixedHeader.value && tagsView.value
|
||||
@@ -168,11 +168,11 @@ export const useRenderLayout = () => {
|
||||
<Menu class="flex-1 px-10px h-[var(--top-tool-height)]"></Menu>
|
||||
<ToolHeader></ToolHeader>
|
||||
</div>
|
||||
<div class={[prefixCls, 'v-content h-full w-full']}>
|
||||
<div class={[`${prefixCls}-content`, 'h-full w-full']}>
|
||||
<ElScrollbar
|
||||
v-loading={pageLoading.value}
|
||||
class={[
|
||||
`${prefixCls}-scrollbar`,
|
||||
`${prefixCls}-content-scrollbar`,
|
||||
{
|
||||
'mt-[var(--tags-view-height)]': fixedHeader.value
|
||||
}
|
||||
@@ -207,10 +207,9 @@ export const useRenderLayout = () => {
|
||||
</div>
|
||||
<div class="absolute top-[var(--logo-height)] left-0 w-full h-[calc(100%-var(--logo-height))] flex">
|
||||
<TabMenu></TabMenu>
|
||||
{/* <Menu class="!h-full"></Menu> */}
|
||||
<div
|
||||
class={[
|
||||
prefixCls,
|
||||
`${prefixCls}-content`,
|
||||
'h-[100%]',
|
||||
{
|
||||
'w-[calc(100%-var(--tab-menu-min-width))] left-[var(--tab-menu-min-width)]':
|
||||
@@ -224,7 +223,7 @@ export const useRenderLayout = () => {
|
||||
<ElScrollbar
|
||||
v-loading={pageLoading.value}
|
||||
class={[
|
||||
`${prefixCls}-scrollbar`,
|
||||
`${prefixCls}-content-scrollbar`,
|
||||
{
|
||||
'!h-[calc(100%-var(--tags-view-height))] mt-[calc(var(--tags-view-height))]':
|
||||
fixedHeader.value && tagsView.value
|
||||
|
||||
@@ -17,7 +17,17 @@ export default {
|
||||
closeTheLeftTab: 'Close left',
|
||||
closeTheRightTab: 'Close right',
|
||||
closeOther: 'Close other',
|
||||
closeAll: 'Close all'
|
||||
closeAll: 'Close all',
|
||||
prevLabel: 'Prev',
|
||||
nextLabel: 'Next',
|
||||
skipLabel: 'Jump',
|
||||
doneLabel: 'End',
|
||||
menu: 'Menu',
|
||||
menuDes: 'Menu bar rendered in routed structure',
|
||||
collapse: 'Collapse',
|
||||
collapseDes: 'Expand and zoom the menu bar',
|
||||
tagsView: 'Tags view',
|
||||
tagsViewDes: 'Used to record routing history'
|
||||
},
|
||||
setting: {
|
||||
projectSetting: 'Project setting',
|
||||
@@ -72,7 +82,8 @@ export default {
|
||||
menu2: 'Menu2',
|
||||
dashboard: 'Dashboard',
|
||||
analysis: 'Analysis',
|
||||
workplace: 'Workplace'
|
||||
workplace: 'Workplace',
|
||||
guide: 'Guide'
|
||||
},
|
||||
analysis: {
|
||||
newUser: 'New user',
|
||||
@@ -173,5 +184,11 @@ export default {
|
||||
timeSelect: 'Time Select',
|
||||
inputPassword: 'input Password',
|
||||
passwordStrength: 'Password Strength'
|
||||
},
|
||||
guideDemo: {
|
||||
guide: 'Guide',
|
||||
start: 'Start',
|
||||
message:
|
||||
'The guide page is very useful for some people who enter the project for the first time. You can briefly introduce the functions of the project. The boot page is based on intro js'
|
||||
}
|
||||
}
|
||||
|
||||
@@ -17,7 +17,17 @@ export default {
|
||||
closeTheLeftTab: '关闭左侧标签页',
|
||||
closeTheRightTab: '关闭右侧标签页',
|
||||
closeOther: '关闭其他标签页',
|
||||
closeAll: '关闭全部标签页'
|
||||
closeAll: '关闭全部标签页',
|
||||
prevLabel: '上一步',
|
||||
nextLabel: '下一步',
|
||||
skipLabel: '跳过',
|
||||
doneLabel: '结束',
|
||||
menu: '菜单',
|
||||
menuDes: '以路由的结构渲染的菜单栏',
|
||||
collapse: '展开缩收',
|
||||
collapseDes: '展开和缩放菜单栏',
|
||||
tagsView: '标签页',
|
||||
tagsViewDes: '用于记录路由历史记录'
|
||||
},
|
||||
setting: {
|
||||
projectSetting: '项目配置',
|
||||
@@ -72,7 +82,8 @@ export default {
|
||||
menu2: '菜单2',
|
||||
dashboard: '首页',
|
||||
analysis: '分析页',
|
||||
workplace: '工作台'
|
||||
workplace: '工作台',
|
||||
guide: '引导'
|
||||
},
|
||||
analysis: {
|
||||
newUser: '新增用户',
|
||||
@@ -173,5 +184,11 @@ export default {
|
||||
timeSelect: '时间选择',
|
||||
inputPassword: '密码输入框',
|
||||
passwordStrength: '密码强度'
|
||||
},
|
||||
guideDemo: {
|
||||
guide: '引导页',
|
||||
start: '开始',
|
||||
message:
|
||||
'引导页对于一些第一次进入项目的人很有用,你可以简单介绍下项目的功能。引导页基于 intro.js'
|
||||
}
|
||||
}
|
||||
|
||||
@@ -68,6 +68,23 @@ export const asyncRouterMap: AppRouteRecordRaw[] = [
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
path: '/guide',
|
||||
component: Layout,
|
||||
name: 'Guide',
|
||||
meta: {},
|
||||
children: [
|
||||
{
|
||||
path: 'index',
|
||||
component: () => import('@/views/Guide/Guide.vue'),
|
||||
name: 'GuideDemo',
|
||||
meta: {
|
||||
title: t('router.guide'),
|
||||
icon: 'cib:telegram-plane'
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
path: '/level',
|
||||
component: Layout,
|
||||
|
||||
20
src/views/Guide/Guide.vue
Normal file
20
src/views/Guide/Guide.vue
Normal file
@@ -0,0 +1,20 @@
|
||||
<script setup lang="ts">
|
||||
import { ContentWrap } from '@/components/ContentWrap'
|
||||
import { useI18n } from '@/hooks/web/useI18n'
|
||||
import { useIntro } from '@/hooks/web/useIntro'
|
||||
import { ElButton } from 'element-plus'
|
||||
|
||||
const { t } = useI18n()
|
||||
|
||||
const { introRef } = useIntro()
|
||||
|
||||
const guideStart = () => {
|
||||
introRef.start()
|
||||
}
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<ContentWrap :title="t('guideDemo.guide')" :message="t('guideDemo.message')">
|
||||
<ElButton type="primary" @click="guideStart">{{ t('guideDemo.start') }}</ElButton>
|
||||
</ContentWrap>
|
||||
</template>
|
||||
Reference in New Issue
Block a user