mirror of
https://github.com/XiaoDaiGua-Ray/ray-template.git
synced 2025-05-22 12:55:18 +08:00
细节补充
This commit is contained in:
parent
753b8e898a
commit
80d05792e8
@ -1,20 +0,0 @@
|
|||||||
@keyframes scaleScreenfull {
|
|
||||||
0% {
|
|
||||||
transform: scale(1);
|
|
||||||
}
|
|
||||||
50% {
|
|
||||||
transform: scale(1.3);
|
|
||||||
}
|
|
||||||
100% {
|
|
||||||
transform: scale(1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.tay-table-icon__screenfull {
|
|
||||||
transition: transform 0.3s var(--r-bezier);
|
|
||||||
|
|
||||||
&:hover {
|
|
||||||
animation: scaleScreenfull 0.3s linear;
|
|
||||||
animation-direction: alternate;
|
|
||||||
}
|
|
||||||
}
|
|
@ -61,7 +61,7 @@ const TableSetting = defineComponent({
|
|||||||
{{
|
{{
|
||||||
trigger: () => (
|
trigger: () => (
|
||||||
<RayIcon
|
<RayIcon
|
||||||
customClassName={`draggable-item__icon ${
|
customClassName={`draggable-item__icon ray-table-icon ${
|
||||||
element[key] ? 'draggable-item__icon--actived' : ''
|
element[key] ? 'draggable-item__icon--actived' : ''
|
||||||
}`}
|
}`}
|
||||||
name={name}
|
name={name}
|
||||||
|
@ -1,4 +1,25 @@
|
|||||||
|
@keyframes scaleScreenfull {
|
||||||
|
0% {
|
||||||
|
transform: scale(1);
|
||||||
|
}
|
||||||
|
50% {
|
||||||
|
transform: scale(1.3);
|
||||||
|
}
|
||||||
|
100% {
|
||||||
|
transform: scale(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
.ray-table {
|
.ray-table {
|
||||||
|
& .ray-table-icon {
|
||||||
|
transition: transform 0.3s var(--r-bezier);
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
animation: scaleScreenfull 0.3s linear;
|
||||||
|
animation-direction: alternate;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
& .ray-table__setting,
|
& .ray-table__setting,
|
||||||
& .ray-table-icon {
|
& .ray-table-icon {
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
|
@ -227,10 +227,6 @@ const RayTable = defineComponent({
|
|||||||
registerRayTableMethods(rayTableInstance.value as DataTableInst)
|
registerRayTableMethods(rayTableInstance.value as DataTableInst)
|
||||||
})
|
})
|
||||||
|
|
||||||
// expose({
|
|
||||||
// tableMethods: tableMethods.value,
|
|
||||||
// })
|
|
||||||
|
|
||||||
return {
|
return {
|
||||||
tableUUID,
|
tableUUID,
|
||||||
rayTableUUID,
|
rayTableUUID,
|
||||||
|
@ -4,6 +4,8 @@ $menuTagWrapperWidth: 76px;
|
|||||||
.menu-tag {
|
.menu-tag {
|
||||||
height: $layoutMenuHeight;
|
height: $layoutMenuHeight;
|
||||||
border-bottom: solid 1px var(--n-border-color);
|
border-bottom: solid 1px var(--n-border-color);
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
|
||||||
& .menu-tag-sapce {
|
& .menu-tag-sapce {
|
||||||
width: calc(100% - $space * 2);
|
width: calc(100% - $space * 2);
|
||||||
|
@ -16,6 +16,9 @@
|
|||||||
* - 关闭右侧: 关闭右侧所有标签, 如果选中标签页与当前激活页不一致并且激活页在右侧, 则会重定向至当前选中标签页
|
* - 关闭右侧: 关闭右侧所有标签, 如果选中标签页与当前激活页不一致并且激活页在右侧, 则会重定向至当前选中标签页
|
||||||
* - 关闭左侧: 关闭左侧所有标签, 如果选中标签页与当前激活页不一致并且激活页在左侧, 则会重定向至当前选中标签页
|
* - 关闭左侧: 关闭左侧所有标签, 如果选中标签页与当前激活页不一致并且激活页在左侧, 则会重定向至当前选中标签页
|
||||||
* - 关闭其他: 关闭其他所有标签, 如果选中标签页与当前激活页不一致并且激活页在其中, 则会重定向至当前选中标签页
|
* - 关闭其他: 关闭其他所有标签, 如果选中标签页与当前激活页不一致并且激活页在其中, 则会重定向至当前选中标签页
|
||||||
|
*
|
||||||
|
* root path 标签不可被关闭, 所以不会显示关闭按钮
|
||||||
|
* 页面刷新后, 仅会保留刷新前激活 key 的 tag 标签
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import './index.scss'
|
import './index.scss'
|
||||||
@ -51,7 +54,25 @@ const MenuTag = defineComponent({
|
|||||||
|
|
||||||
const exclude = ['closeAll', 'closeRight', 'closeLeft', 'closeOther']
|
const exclude = ['closeAll', 'closeRight', 'closeLeft', 'closeOther']
|
||||||
let currentContentmenuIndex = -1 // 当前右键标签页索引位置
|
let currentContentmenuIndex = -1 // 当前右键标签页索引位置
|
||||||
const modelMenuTagOptions = computed(() => menuTagOptions.value)
|
const modelMenuTagOptions = computed(() =>
|
||||||
|
menuTagOptions.value.map((curr, _idx, currentArray) => {
|
||||||
|
if (curr.key === menuKey.value && curr.key !== path) {
|
||||||
|
curr.closeable = true
|
||||||
|
} else {
|
||||||
|
curr.closeable = false
|
||||||
|
}
|
||||||
|
|
||||||
|
if (curr.key === path) {
|
||||||
|
curr.closeable = false
|
||||||
|
}
|
||||||
|
|
||||||
|
if (currentArray.length <= 1) {
|
||||||
|
curr.closeable = false
|
||||||
|
}
|
||||||
|
|
||||||
|
return curr
|
||||||
|
}),
|
||||||
|
)
|
||||||
const moreOptions = ref([
|
const moreOptions = ref([
|
||||||
{
|
{
|
||||||
label: '重新加载',
|
label: '重新加载',
|
||||||
@ -309,6 +330,20 @@ const MenuTag = defineComponent({
|
|||||||
setDisabledAccordionToIndex()
|
setDisabledAccordionToIndex()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** 仅有 modelMenuTagOptions 长度大于 1 并且非 root path 时, 才激活关闭按钮 */
|
||||||
|
const menuTagMouseenter = (option: MenuTagOptions) => {
|
||||||
|
if (modelMenuTagOptions.value.length > 1 && option.key !== path) {
|
||||||
|
option.closeable = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 移出 MenuTag 时, 判断是否为当前已激活 key */
|
||||||
|
const menuTagMouseleave = (option: MenuTagOptions) => {
|
||||||
|
if (option.key !== menuKey.value) {
|
||||||
|
option.closeable = false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/** 如果有且只有一个标签页时, 禁止全部关闭操作 */
|
/** 如果有且只有一个标签页时, 禁止全部关闭操作 */
|
||||||
watch(
|
watch(
|
||||||
() => modelMenuTagOptions.value,
|
() => modelMenuTagOptions.value,
|
||||||
@ -350,6 +385,8 @@ const MenuTag = defineComponent({
|
|||||||
actionState,
|
actionState,
|
||||||
handleContextMenu,
|
handleContextMenu,
|
||||||
setCurrentContentmenuIndex,
|
setCurrentContentmenuIndex,
|
||||||
|
menuTagMouseenter,
|
||||||
|
menuTagMouseleave,
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
render() {
|
render() {
|
||||||
@ -389,6 +426,10 @@ const MenuTag = defineComponent({
|
|||||||
{...{
|
{...{
|
||||||
id: this.scrollBarUUID,
|
id: this.scrollBarUUID,
|
||||||
}}
|
}}
|
||||||
|
themeOverrides={{
|
||||||
|
color: 'rgba(0, 0, 0, 0)',
|
||||||
|
colorHover: 'rgba(0, 0, 0, 0)',
|
||||||
|
}}
|
||||||
>
|
>
|
||||||
<NSpace
|
<NSpace
|
||||||
class="menu-tag-wrapper"
|
class="menu-tag-wrapper"
|
||||||
@ -398,16 +439,17 @@ const MenuTag = defineComponent({
|
|||||||
>
|
>
|
||||||
{this.modelMenuTagOptions.map((curr, idx) => (
|
{this.modelMenuTagOptions.map((curr, idx) => (
|
||||||
<NTag
|
<NTag
|
||||||
closable={
|
size="large"
|
||||||
curr.key !== this.rootPath &&
|
strong
|
||||||
this.modelMenuTagOptions.length > 1
|
closable={curr.closeable}
|
||||||
}
|
|
||||||
onClose={this.closeCurrentMenuTag.bind(this, idx)}
|
onClose={this.closeCurrentMenuTag.bind(this, idx)}
|
||||||
type={curr.key === this.menuKey ? 'primary' : 'default'}
|
type={curr.key === this.menuKey ? 'primary' : 'default'}
|
||||||
bordered={false}
|
bordered={false}
|
||||||
{...{
|
{...{
|
||||||
onClick: this.handleTagClick.bind(this, curr),
|
onClick: this.handleTagClick.bind(this, curr),
|
||||||
onContextmenu: this.handleContextMenu.bind(this, idx),
|
onContextmenu: this.handleContextMenu.bind(this, idx),
|
||||||
|
onMouseenter: this.menuTagMouseenter.bind(this, curr),
|
||||||
|
onMouseleave: this.menuTagMouseleave.bind(this, curr),
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
{typeof curr.label === 'function'
|
{typeof curr.label === 'function'
|
||||||
|
@ -19,7 +19,7 @@ import Breadcrumb from './components/Breadcrumb/index'
|
|||||||
import GlobalSeach from './components/GlobalSeach/index'
|
import GlobalSeach from './components/GlobalSeach/index'
|
||||||
import AppAvatar from '@/components/AppComponents/AppAvatar/index'
|
import AppAvatar from '@/components/AppComponents/AppAvatar/index'
|
||||||
|
|
||||||
import { useSetting, useSignin } from '@/store'
|
import { useSetting } from '@/store'
|
||||||
import { LOCAL_OPTIONS } from '@/appConfig/localConfig'
|
import { LOCAL_OPTIONS } from '@/appConfig/localConfig'
|
||||||
import { useAvatarOptions, avatarDropdownClick } from './hook'
|
import { useAvatarOptions, avatarDropdownClick } from './hook'
|
||||||
import { getCache } from '@/utils/cache'
|
import { getCache } from '@/utils/cache'
|
||||||
@ -38,13 +38,11 @@ import type { IconEventMapOptions, IconEventMap } from './type'
|
|||||||
|
|
||||||
const SiderBar = defineComponent({
|
const SiderBar = defineComponent({
|
||||||
name: 'SiderBar',
|
name: 'SiderBar',
|
||||||
setup() {
|
setup(_, { expose }) {
|
||||||
const settingStore = useSetting()
|
const settingStore = useSetting()
|
||||||
const signinStore = useSignin()
|
|
||||||
|
|
||||||
const { t } = useI18n()
|
const { t } = useI18n()
|
||||||
const { updateLocale, changeSwitcher } = settingStore
|
const { updateLocale, changeSwitcher } = settingStore
|
||||||
const { logout } = signinStore
|
|
||||||
|
|
||||||
const { drawerPlacement, breadcrumbSwitch } = storeToRefs(settingStore)
|
const { drawerPlacement, breadcrumbSwitch } = storeToRefs(settingStore)
|
||||||
const showSettings = ref(false)
|
const showSettings = ref(false)
|
||||||
@ -126,6 +124,8 @@ const SiderBar = defineComponent({
|
|||||||
iconEventMap[key]?.()
|
iconEventMap[key]?.()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// expose({})
|
||||||
|
|
||||||
return {
|
return {
|
||||||
leftIconOptions,
|
leftIconOptions,
|
||||||
rightTooltipIconOptions,
|
rightTooltipIconOptions,
|
||||||
|
@ -5,6 +5,10 @@
|
|||||||
height: 100%;
|
height: 100%;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
& .layout__view-container__layout .n-layout-scroll-container {
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
& .layout-content__router-view {
|
& .layout-content__router-view {
|
||||||
height: var(--layout-content-height);
|
height: var(--layout-content-height);
|
||||||
padding: calc($layoutRouterViewContainer / 2);
|
padding: calc($layoutRouterViewContainer / 2);
|
||||||
|
@ -3,7 +3,10 @@
|
|||||||
* 页面布局入口文件
|
* 页面布局入口文件
|
||||||
*
|
*
|
||||||
* 说明:
|
* 说明:
|
||||||
* - rayLayoutContentWrapperScopeSelector: 页面切换时重置滚动条注入 id
|
* - rayLayoutContentWrapperScopeSelector: 页面切换时重置滚动条注入 id(弃用)
|
||||||
|
*
|
||||||
|
* 该组件入口不做逻辑相关的处理, 仅做功能、组件、方法注入
|
||||||
|
* 提供页面内 Layout 的一些注入(css vars 为主)
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import './index.scss'
|
import './index.scss'
|
||||||
@ -20,36 +23,31 @@ import {
|
|||||||
viewScrollContainerId,
|
viewScrollContainerId,
|
||||||
LAYOUT_CONTENT_REF,
|
LAYOUT_CONTENT_REF,
|
||||||
} from '@/appConfig/routerConfig'
|
} from '@/appConfig/routerConfig'
|
||||||
|
import { layoutHeaderCssVars } from '@/layout/layoutResize'
|
||||||
|
|
||||||
const Layout = defineComponent({
|
const Layout = defineComponent({
|
||||||
name: 'RLayout',
|
name: 'RLayout',
|
||||||
setup() {
|
setup() {
|
||||||
|
const layoutSiderBarRef = ref<HTMLElement>()
|
||||||
|
const layoutMenuTagRef = ref<HTMLElement>()
|
||||||
|
|
||||||
const settingStore = useSetting()
|
const settingStore = useSetting()
|
||||||
const menuStore = useMenu()
|
const menuStore = useMenu()
|
||||||
|
|
||||||
const { height: windowHeight } = useWindowSize()
|
const { height: windowHeight } = useWindowSize()
|
||||||
const { menuTagSwitch: modelMenuTagSwitch } = storeToRefs(settingStore)
|
const { menuTagSwitch: modelMenuTagSwitch } = storeToRefs(settingStore)
|
||||||
const { setupAppRoutes } = menuStore
|
const { setupAppRoutes } = menuStore
|
||||||
const cssVarsRef = computed(() => {
|
|
||||||
let cssVar = {}
|
|
||||||
|
|
||||||
if (settingStore.menuTagSwitch) {
|
|
||||||
cssVar = {
|
|
||||||
'--layout-content-height': 'calc(100% - 111px)',
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
cssVar = {
|
|
||||||
'--layout-content-height': 'calc(100% - 64px)',
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return cssVar
|
|
||||||
})
|
|
||||||
const isLock = useStorage('isLockScreen', false, sessionStorage, {
|
const isLock = useStorage('isLockScreen', false, sessionStorage, {
|
||||||
mergeDefaults: true,
|
mergeDefaults: true,
|
||||||
})
|
})
|
||||||
|
const cssVarsRef = layoutHeaderCssVars([
|
||||||
|
layoutSiderBarRef,
|
||||||
|
layoutMenuTagRef,
|
||||||
|
])
|
||||||
|
|
||||||
setupAppRoutes()
|
nextTick().then(() => {
|
||||||
|
setupAppRoutes()
|
||||||
|
})
|
||||||
|
|
||||||
return {
|
return {
|
||||||
windowHeight,
|
windowHeight,
|
||||||
@ -57,6 +55,8 @@ const Layout = defineComponent({
|
|||||||
cssVarsRef,
|
cssVarsRef,
|
||||||
isLock,
|
isLock,
|
||||||
LAYOUT_CONTENT_REF,
|
LAYOUT_CONTENT_REF,
|
||||||
|
layoutSiderBarRef,
|
||||||
|
layoutMenuTagRef,
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
render() {
|
render() {
|
||||||
@ -68,9 +68,13 @@ const Layout = defineComponent({
|
|||||||
{!this.isLock ? (
|
{!this.isLock ? (
|
||||||
<NLayout class="layout-full" hasSider>
|
<NLayout class="layout-full" hasSider>
|
||||||
<Menu />
|
<Menu />
|
||||||
<NLayout>
|
<NLayout class="layout__view-container__layout">
|
||||||
<SiderBar />
|
<SiderBar ref="layoutSiderBarRef" />
|
||||||
{this.modelMenuTagSwitch ? <MenuTag /> : ''}
|
{this.modelMenuTagSwitch ? (
|
||||||
|
<MenuTag ref="layoutMenuTagRef" />
|
||||||
|
) : (
|
||||||
|
''
|
||||||
|
)}
|
||||||
<NLayoutContent
|
<NLayoutContent
|
||||||
ref="LAYOUT_CONTENT_REF"
|
ref="LAYOUT_CONTENT_REF"
|
||||||
class="layout-content__router-view"
|
class="layout-content__router-view"
|
||||||
|
35
src/layout/layoutResize.ts
Normal file
35
src/layout/layoutResize.ts
Normal file
@ -0,0 +1,35 @@
|
|||||||
|
/**
|
||||||
|
*
|
||||||
|
* @author Ray <https://github.com/XiaoDaiGua-Ray>
|
||||||
|
*
|
||||||
|
* @date 2023-06-02
|
||||||
|
*
|
||||||
|
* @workspace ray-template
|
||||||
|
*
|
||||||
|
* @remark 今天也是元气满满撸代码的一天
|
||||||
|
*/
|
||||||
|
|
||||||
|
import type { Ref } from 'vue'
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* 动态获取 SiderBar 和 MenuTag 高度, 用于 LayoutConetent 高度实时获取与渲染
|
||||||
|
* 可以动态更改 MenuTag 样式后, 使得 LayoutConetent 也可以准确的获取高度
|
||||||
|
*
|
||||||
|
* 基于 vueuse useElementSize 方法实现
|
||||||
|
* 不建议滥用该方法, 对页面渲染有一定的影响
|
||||||
|
*/
|
||||||
|
export const layoutHeaderCssVars = (
|
||||||
|
element: Ref<HTMLElement | undefined>[],
|
||||||
|
) => {
|
||||||
|
const siderBar = useElementSize(element[0])
|
||||||
|
const menuTag = useElementSize(element[1])
|
||||||
|
|
||||||
|
return computed(() => {
|
||||||
|
return {
|
||||||
|
'--layout-content-height': `calc(100% - ${siderBar.height.value}px - ${menuTag.height.value}px)`,
|
||||||
|
'--layout-siderbar-height': `${siderBar.height.value}px`,
|
||||||
|
'--layout-menutag-height': `${menuTag.height.value}px`,
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
@ -45,10 +45,10 @@ export const useMenu = defineStore(
|
|||||||
const { t } = useI18n()
|
const { t } = useI18n()
|
||||||
const { setKeepAliveInclude } = useKeepAlive()
|
const { setKeepAliveInclude } = useKeepAlive()
|
||||||
|
|
||||||
const { path } = ROOT_ROUTE
|
const { path: rootPath } = ROOT_ROUTE
|
||||||
|
|
||||||
const cacheMenuKey =
|
const cacheMenuKey =
|
||||||
getCache('menuKey') === 'no' ? path : getCache('menuKey')
|
getCache('menuKey') === 'no' ? rootPath : getCache('menuKey')
|
||||||
|
|
||||||
const menuState = reactive({
|
const menuState = reactive({
|
||||||
menuKey: cacheMenuKey as MenuKey, // 当前菜单 `key`
|
menuKey: cacheMenuKey as MenuKey, // 当前菜单 `key`
|
||||||
|
4
src/types/store.d.ts
vendored
4
src/types/store.d.ts
vendored
@ -18,7 +18,9 @@ declare global {
|
|||||||
noLocalTitle?: string | number
|
noLocalTitle?: string | number
|
||||||
}
|
}
|
||||||
|
|
||||||
declare interface MenuTagOptions extends IMenuOptions {}
|
declare interface MenuTagOptions extends IMenuOptions {
|
||||||
|
closeable?: boolean
|
||||||
|
}
|
||||||
|
|
||||||
declare type MenuKey = null | string | number
|
declare type MenuKey = null | string | number
|
||||||
}
|
}
|
||||||
|
@ -109,6 +109,22 @@ export const hasClass = (element: HTMLElement, className: string) => {
|
|||||||
*
|
*
|
||||||
* @param el Target element dom
|
* @param el Target element dom
|
||||||
* @param styles 所需绑定样式(如果为字符串, 则必须以分号结尾每个行内样式描述)
|
* @param styles 所需绑定样式(如果为字符串, 则必须以分号结尾每个行内样式描述)
|
||||||
|
*
|
||||||
|
* style of string
|
||||||
|
* ```
|
||||||
|
* const styles = 'width: 100px; height: 100px; background: red;'
|
||||||
|
*
|
||||||
|
* addStyle(styles)
|
||||||
|
* ```
|
||||||
|
* style of object
|
||||||
|
* ```
|
||||||
|
* const styles = {
|
||||||
|
* width: '100px',
|
||||||
|
* height: '100px',
|
||||||
|
* }
|
||||||
|
*
|
||||||
|
* addStyle(styles)
|
||||||
|
* ```
|
||||||
*/
|
*/
|
||||||
export const addStyle = (
|
export const addStyle = (
|
||||||
el: HTMLElement,
|
el: HTMLElement,
|
||||||
|
Loading…
x
Reference in New Issue
Block a user