This commit is contained in:
XiaoDaiGua-Ray 2023-08-01 16:20:43 +08:00
parent 8277cbc4b8
commit 20757214d8
22 changed files with 159 additions and 103 deletions

2
.npmrc
View File

@ -1,4 +1,4 @@
package-lock=false package-lock=true
prefer-offline=true prefer-offline=true
save-exact=true save-exact=true
engine-strict=true engine-strict=true

View File

@ -1,5 +1,19 @@
# CHANGE LOG # CHANGE LOG
## 4.1.4
该版本后,不会做破坏性更新了。版本功能趋于稳定,后续更新不会那么频繁了。。。。。
### Feats
- 新增版权信息开关
- 做了一些小小的细节更新
### Fixes
- 修复获取部分元素高度不准确导致布局一些小问题
- 修复底部版权信息展示问题
## 4.1.3 ## 4.1.3
### Feats ### Feats

View File

@ -30,11 +30,12 @@ import type { LayoutInst } from 'naive-ui'
*/ */
export const LAYOUT_CONTENT_REF = ref<LayoutInst>() export const LAYOUT_CONTENT_REF = ref<LayoutInst>()
/** 是否启用路由切换时顶部加载条 */ export const SETUP_ROUTER_ACTION = {
export const SETUP_ROUTER_LOADING_BAR = true /** 是否启用路由切换时顶部加载条 */
setupRouterLoadingBar: true,
/** 是否启用路由守卫, 如果设置为 false 则不会触发路由切换校验 */ /** 是否启用路由守卫, 如果设置为 false 则不会触发路由切换校验 */
export const SETUP_ROUTER_GUARD = true setupRouterGuard: true,
} as const
/** /**
* *

View File

@ -12,6 +12,7 @@
import './index.scss' import './index.scss'
import { call } from '@/utils/vue/index' import { call } from '@/utils/vue/index'
import { completeSize } from '@/utils/element'
import type { PropType } from 'vue' import type { PropType } from 'vue'
import type { MaybeArray } from '@/types/modules/utils' import type { MaybeArray } from '@/types/modules/utils'
@ -69,11 +70,11 @@ const RayIcon = defineComponent({
const cssVars = computed(() => { const cssVars = computed(() => {
const cssVar = { const cssVar = {
'--ray-icon-width': props.width '--ray-icon-width': props.width
? props.width + 'px' ? completeSize(props.width)
: props.size + 'px', : completeSize(props.size),
'--ray-icon-height': props.height '--ray-icon-height': props.height
? props.height + 'px' ? completeSize(props.height)
: props.size + 'px', : completeSize(props.size),
'--ray-icon-depth': props.depth, '--ray-icon-depth': props.depth,
'--ray-icon-cursor': props.cursor, '--ray-icon-cursor': props.cursor,
} }

View File

@ -142,7 +142,9 @@ const RayIframe = defineComponent({
return iframeEl return iframeEl
} }
expose() expose({
iframeInst: iframeRef,
})
onMounted(() => { onMounted(() => {
on(getIframeRef(), 'load', iframeLoadSuccess.bind(this)) on(getIframeRef(), 'load', iframeLoadSuccess.bind(this))

View File

@ -36,8 +36,8 @@ const rayTableProps = {
* *
* *
*/ */
type: [String, Object] as PropType<string | VNodeChild>, type: [String, Object] as PropType<VNodeChild | string>,
default: '', default: null,
}, },
action: { action: {
/** /**
@ -208,7 +208,6 @@ const rayTableProps = {
default: false, default: false,
}, },
} as const } as const
export default rayTableProps export default rayTableProps
/** /**

View File

@ -61,6 +61,11 @@ const GlobalSeach = defineComponent({
label: '切换', label: '切换',
plain: true, plain: true,
}, },
{
icon: '↵',
label: '选择',
plain: true,
},
{ {
icon: 'esc', icon: 'esc',
label: '关闭', label: '关闭',

View File

@ -46,6 +46,7 @@ const SettingDrawer = defineComponent({
menuTagSwitch, menuTagSwitch,
breadcrumbSwitch, breadcrumbSwitch,
invertSwitch, invertSwitch,
footerSwitch,
} = storeToRefs(settingStore) } = storeToRefs(settingStore)
const modelShow = computed({ const modelShow = computed({
@ -65,6 +66,7 @@ const SettingDrawer = defineComponent({
changeSwitcher, changeSwitcher,
breadcrumbSwitch, breadcrumbSwitch,
invertSwitch, invertSwitch,
footerSwitch,
} }
}, },
render() { render() {
@ -110,6 +112,14 @@ const SettingDrawer = defineComponent({
} }
/> />
</NDescriptionsItem> </NDescriptionsItem>
<NDescriptionsItem label="版权信息">
<NSwitch
v-model:value={this.footerSwitch}
onUpdateValue={(bool: boolean) =>
this.changeSwitcher(bool, 'footerSwitch')
}
/>
</NDescriptionsItem>
<NDescriptionsItem label="反转色"> <NDescriptionsItem label="反转色">
<NSwitch <NSwitch
v-model:value={this.invertSwitch} v-model:value={this.invertSwitch}

View File

@ -26,11 +26,11 @@ const TooltipIcon = defineComponent({
}, },
customClassName: { customClassName: {
type: String, type: String,
default: '', default: null,
}, },
tooltipText: { tooltipText: {
type: String, type: String,
default: '', default: null,
}, },
}, },
emits: ['click'], emits: ['click'],
@ -51,6 +51,7 @@ const TooltipIcon = defineComponent({
name={this.iconName} name={this.iconName}
size="18" size="18"
customClassName={`tooltip-text__icon ${this.customClassName}`} customClassName={`tooltip-text__icon ${this.customClassName}`}
cursor="pointer"
onClick={this.handleClick.bind(this)} onClick={this.handleClick.bind(this)}
/> />
), ),

View File

@ -7,10 +7,8 @@
> .layout-header__method { > .layout-header__method {
width: 100%; width: 100%;
& .layout-header__method--icon { & .ray-icon__reload--loading {
cursor: pointer; animation: elementRotate 0.8s linear infinite;
outline: none;
border: none;
} }
} }
} }

View File

@ -12,8 +12,9 @@
/** /**
* *
* , ... * , ...
*
* , * ,
*
* diy 西使 computed
*/ */
import './index.scss' import './index.scss'
@ -33,7 +34,6 @@ import screenfull from 'screenfull'
import { useI18n } from '@/locales/useI18n' import { useI18n } from '@/locales/useI18n'
import type { IconEventMapOptions, IconEventMap } from './type' import type { IconEventMapOptions, IconEventMap } from './type'
import type { SigninCallback } from '@/store/modules/signin/type'
const SiderBar = defineComponent({ const SiderBar = defineComponent({
name: 'SiderBar', name: 'SiderBar',
@ -43,12 +43,14 @@ const SiderBar = defineComponent({
const { t } = useI18n() const { t } = useI18n()
const { updateLocale, changeSwitcher } = settingStore const { updateLocale, changeSwitcher } = settingStore
const { drawerPlacement, breadcrumbSwitch } = storeToRefs(settingStore) const { drawerPlacement, breadcrumbSwitch, reloadRouteSwitch } =
storeToRefs(settingStore)
const showSettings = ref(false) const showSettings = ref(false)
const spaceItemStyle = { const spaceItemStyle = {
display: 'flex', display: 'flex',
} }
const globalSearchShown = ref(false) const globalSearchShown = ref(false)
const isScreenfull = ref(screenfull.isFullscreen)
/** /**
* *
@ -59,6 +61,9 @@ const SiderBar = defineComponent({
name: 'reload', name: 'reload',
size: 18, size: 18,
tooltip: t('headerTooltip.Reload'), tooltip: t('headerTooltip.Reload'),
iconClass: computed(() =>
!reloadRouteSwitch.value ? 'ray-icon__reload--loading' : '',
),
}, },
]) ])
/** /**
@ -75,7 +80,11 @@ const SiderBar = defineComponent({
{ {
name: 'fullscreen', name: 'fullscreen',
size: 18, size: 18,
tooltip: t('headerTooltip.FullScreen'), tooltip: computed(() =>
isScreenfull.value
? t('headerTooltip.CancelFullScreen')
: t('headerTooltip.FullScreen'),
),
eventKey: 'screen', eventKey: 'screen',
}, },
{ {
@ -92,10 +101,11 @@ const SiderBar = defineComponent({
}, },
]) ])
const iconEventMap: IconEventMapOptions = { const iconEventMap: IconEventMapOptions = {
// 刷新组件重新加载,手动设置 800ms loading 时长
reload: () => { reload: () => {
changeSwitcher(false, 'reloadRouteSwitch') changeSwitcher(false, 'reloadRouteSwitch')
setTimeout(() => changeSwitcher(true, 'reloadRouteSwitch'), 300) setTimeout(() => changeSwitcher(true, 'reloadRouteSwitch'), 800)
}, },
setting: () => { setting: () => {
showSettings.value = true showSettings.value = true
@ -111,6 +121,8 @@ const SiderBar = defineComponent({
} else { } else {
return (() => { return (() => {
screenfull.toggle() screenfull.toggle()
isScreenfull.value = !screenfull.isFullscreen
})() })()
} }
}, },
@ -158,9 +170,14 @@ const SiderBar = defineComponent({
{{ {{
trigger: () => ( trigger: () => (
<RayIcon <RayIcon
customClassName="layout-header__method--icon" customClassName={`${
isRef(curr.iconClass)
? curr.iconClass.value
: curr.iconClass
}`}
name={curr.name} name={curr.name}
size={curr.size} size={curr.size}
cursor="pointer"
onClick={this.handleIconClick.bind(this, curr.name)} onClick={this.handleIconClick.bind(this, curr.name)}
/> />
), ),
@ -178,7 +195,9 @@ const SiderBar = defineComponent({
{this.rightTooltipIconOptions.map((curr) => ( {this.rightTooltipIconOptions.map((curr) => (
<TootipIcon <TootipIcon
iconName={curr.name} iconName={curr.name}
tooltipText={curr.tooltip} tooltipText={
isRef(curr.tooltip) ? curr.tooltip.value : curr.tooltip
}
onClick={this.handleIconClick.bind(this, curr.name)} onClick={this.handleIconClick.bind(this, curr.name)}
/> />
))} ))}
@ -193,6 +212,7 @@ const SiderBar = defineComponent({
customClassName="layout-header__method--icon" customClassName="layout-header__method--icon"
name="language" name="language"
size="18" size="18"
cursor="pointer"
/> />
</NDropdown> </NDropdown>
<NDropdown <NDropdown

View File

@ -1,4 +1,4 @@
.layout-footer-wrapper { .layout-footer-wrapper {
padding: 24px; padding: 20px;
text-align: center; text-align: center;
} }

View File

@ -1,23 +1,22 @@
.layout { .r-layout-full.r-layout-full {
box-sizing: border-box; position: fixed;
inset: 0;
> .layout-full { & .n-layout-scroll-container {
height: 100%; & .r-layout-full__viewer .n-layout-scroll-container {
} overflow: hidden;
& .layout__view-container__layout .n-layout-scroll-container { & .r-layout-full__viewer-content {
overflow: hidden; height: var(--layout-content-height);
} padding: 16px;
& .layout-content__router-view { & .n-scrollbar-container {
height: var(--layout-content-height); height: 100%;
padding: calc($layoutRouterViewContainer / 2);
& .n-scrollbar-container { & .n-scrollbar-content {
height: 100%; height: 100%;
}
& .n-scrollbar-content { }
height: 100%;
} }
} }
} }

View File

@ -11,7 +11,7 @@
import './index.scss' import './index.scss'
import { NLayout, NLayoutContent } from 'naive-ui' import { NLayout, NLayoutContent, NScrollbar } from 'naive-ui'
import Menu from './components/Menu/index' import Menu from './components/Menu/index'
import SiderBar from './components/SiderBar/index' import SiderBar from './components/SiderBar/index'
import MenuTag from './components/MenuTag/index' import MenuTag from './components/MenuTag/index'
@ -28,57 +28,49 @@ const Layout = defineComponent({
setup() { setup() {
const layoutSiderBarRef = ref<HTMLElement>() const layoutSiderBarRef = ref<HTMLElement>()
const layoutMenuTagRef = ref<HTMLElement>() const layoutMenuTagRef = ref<HTMLElement>()
const layoutFooterRef = ref<HTMLElement>()
const settingStore = useSetting() const settingStore = useSetting()
const { height: windowHeight } = useWindowSize() const { menuTagSwitch: modelMenuTagSwitch, footerSwitch } =
const { menuTagSwitch: modelMenuTagSwitch } = storeToRefs(settingStore) storeToRefs(settingStore)
const { getLockAppScreen } = useAppLockScreen() const { getLockAppScreen } = useAppLockScreen()
const cssVarsRef = layoutHeaderCssVars([ const cssVarsRef = layoutHeaderCssVars([
layoutSiderBarRef, layoutSiderBarRef,
layoutMenuTagRef, layoutMenuTagRef,
layoutFooterRef,
]) ])
return { return {
windowHeight,
modelMenuTagSwitch, modelMenuTagSwitch,
cssVarsRef, cssVarsRef,
getLockAppScreen, getLockAppScreen,
LAYOUT_CONTENT_REF, LAYOUT_CONTENT_REF,
layoutSiderBarRef, layoutSiderBarRef,
layoutMenuTagRef, layoutMenuTagRef,
layoutFooterRef,
footerSwitch,
} }
}, },
render() { render() {
return ( return !this.getLockAppScreen() ? (
<div <NLayout class="r-layout-full" style={[this.cssVarsRef]} hasSider>
class={['layout']} <Menu />
style={[`height: ${this.windowHeight}px`, this.cssVarsRef]} <NLayoutContent class="r-layout-full__viewer">
> <SiderBar ref="layoutSiderBarRef" />
{!this.getLockAppScreen() ? ( {this.modelMenuTagSwitch ? <MenuTag ref="layoutMenuTagRef" /> : ''}
<NLayout class="layout-full" hasSider> <NLayoutContent
<Menu /> ref="LAYOUT_CONTENT_REF"
<NLayout class="layout__view-container__layout"> class="r-layout-full__viewer-content"
<SiderBar ref="layoutSiderBarRef" /> nativeScrollbar={false}
{this.modelMenuTagSwitch ? ( >
<MenuTag ref="layoutMenuTagRef" /> <ContentWrapper />
) : ( </NLayoutContent>
'' {this.footerSwitch ? <FooterWrapper ref="layoutFooterRef" /> : ''}
)} </NLayoutContent>
<NLayoutContent </NLayout>
ref="LAYOUT_CONTENT_REF" ) : (
class="layout-content__router-view" ''
nativeScrollbar={false}
>
<ContentWrapper />
<FooterWrapper />
</NLayoutContent>
</NLayout>
</NLayout>
) : (
''
)}
</div>
) )
}, },
}) })

View File

@ -22,12 +22,13 @@ import type { Ref } from 'vue'
export const layoutHeaderCssVars = ( export const layoutHeaderCssVars = (
element: Ref<HTMLElement | undefined>[], element: Ref<HTMLElement | undefined>[],
) => { ) => {
const siderBar = useElementSize(element[0]) const siderBar = useElementBounding(element[0])
const menuTag = useElementSize(element[1]) const menuTag = useElementBounding(element[1])
const footer = useElementBounding(element[2])
return computed(() => { return computed(() => {
return { return {
'--layout-content-height': `calc(100% - ${siderBar.height.value}px - ${menuTag.height.value}px)`, '--layout-content-height': `calc(100% - ${siderBar.height.value}px - ${menuTag.height.value}px - ${footer.height.value}px)`,
'--layout-siderbar-height': `${siderBar.height.value}px`, '--layout-siderbar-height': `${siderBar.height.value}px`,
'--layout-menutag-height': `${menuTag.height.value}px`, '--layout-menutag-height': `${menuTag.height.value}px`,
} }

View File

@ -27,12 +27,7 @@ import { WHITE_ROUTES } from '@/appConfig/routerConfig'
import { validRole } from '@/router/helper/routerCopilot' import { validRole } from '@/router/helper/routerCopilot'
import { isValueType } from '@/utils/hook' import { isValueType } from '@/utils/hook'
import type { import type { Router, RouteLocationNormalized } from 'vue-router'
Router,
NavigationGuardNext,
RouteLocationNormalized,
} from 'vue-router'
import type { AppMenuOption } from '@/types/modules/app'
import type { AppRouteMeta } from '@/router/type' import type { AppRouteMeta } from '@/router/type'
/** 路由守卫 */ /** 路由守卫 */

View File

@ -10,11 +10,7 @@
*/ */
import { permissionRouter } from './permission' import { permissionRouter } from './permission'
import { import { SETUP_ROUTER_ACTION, SUPER_ADMIN } from '@/appConfig/routerConfig'
SETUP_ROUTER_LOADING_BAR,
SETUP_ROUTER_GUARD,
SUPER_ADMIN,
} from '@/appConfig/routerConfig'
import { useSignin } from '@/store' import { useSignin } from '@/store'
import { useVueRouter } from '@/router/helper/useVueRouter' import { useVueRouter } from '@/router/helper/useVueRouter'
import { ROOT_ROUTE } from '@/appConfig/appConfig' import { ROOT_ROUTE } from '@/appConfig/appConfig'
@ -112,11 +108,14 @@ export const setupRouterLoadingBar = (router: Router) => {
* @remark , ... * @remark , ...
*/ */
export const vueRouterRegister = (router: Router) => { export const vueRouterRegister = (router: Router) => {
if (SETUP_ROUTER_LOADING_BAR) { const { setupRouterLoadingBar: cfgSetupRouterLoadingBar, setupRouterGuard } =
SETUP_ROUTER_ACTION
if (cfgSetupRouterLoadingBar) {
setupRouterLoadingBar(router) setupRouterLoadingBar(router)
} }
if (SETUP_ROUTER_GUARD) { if (setupRouterGuard) {
permissionRouter(router) permissionRouter(router)
} }
} }

View File

@ -37,6 +37,7 @@ export const useSetting = defineStore(
localeLanguage: getAppDefaultLanguage(), localeLanguage: getAppDefaultLanguage(),
lockScreenSwitch: false, // 锁屏开关 lockScreenSwitch: false, // 锁屏开关
lockScreenInputSwitch: false, // 锁屏输入状态开关(预留该字段是为了方便拓展用, 但是舍弃了该字段, 改为使用 useAppLockScreen 方法) lockScreenInputSwitch: false, // 锁屏输入状态开关(预留该字段是为了方便拓展用, 但是舍弃了该字段, 改为使用 useAppLockScreen 方法)
footerSwitch: true, // 底部区域开关
}) })
/** 修改当前语言 */ /** 修改当前语言 */

View File

@ -13,4 +13,5 @@ export interface SettingState {
invertSwitch: boolean invertSwitch: boolean
lockScreenSwitch: boolean lockScreenSwitch: boolean
lockScreenInputSwitch: boolean lockScreenInputSwitch: boolean
footerSwitch: boolean
} }

View File

@ -1,3 +1,14 @@
// css vars root
:root { :root {
--r-bezier: cubic-bezier(0.4, 0, 0.2, 1); --r-bezier: cubic-bezier(0.4, 0, 0.2, 1);
} }
// animation root
@keyframes elementRotate {
from {
transform: rotate(0deg);
}
to {
transform: rotate(360deg);
}
}

View File

@ -22,7 +22,11 @@ const MultiMenuTwoOne = defineComponent({
}, },
render() { render() {
return ( return (
<div> <div
style={{
height: 'var(--layout-content-height)',
}}
>
2-2-1 2-2-1
<NInput v-model={this.inputValue} /> <NInput v-model={this.inputValue} />
</div> </div>

View File

@ -22,6 +22,7 @@ import {
NH2, NH2,
NUl, NUl,
NLi, NLi,
NSpace,
} from 'naive-ui' } from 'naive-ui'
import RayTable from '@/components/RayTable/index' import RayTable from '@/components/RayTable/index'
import RayCollapseGrid from '@/components/RayCollapseGrid/index' import RayCollapseGrid from '@/components/RayCollapseGrid/index'
@ -163,7 +164,7 @@ const TableView = defineComponent({
}, },
render() { render() {
return ( return (
<NLayout> <div>
<NH2>RayTable 使</NH2> <NH2>RayTable 使</NH2>
<NUl alignText> <NUl alignText>
<NLi> <NLi>
@ -231,13 +232,14 @@ const TableView = defineComponent({
style="margin-top: 18px" style="margin-top: 18px"
ref="tableRef" ref="tableRef"
scrollX={2000} scrollX={2000}
title={h( title={
NSwitch, <NSpace align="center">
{ <span>:</span>
onUpdateValue: (value: boolean) => (this.tableLoading = value), <NSwitch
}, onUpdateValue={(value: boolean) => (this.tableLoading = value)}
{}, ></NSwitch>
)} </NSpace>
}
data={this.tableData} data={this.tableData}
v-model:columns={this.actionColumns} v-model:columns={this.actionColumns}
pagination={{ pagination={{
@ -251,7 +253,7 @@ const TableView = defineComponent({
tableFooter: () => '表格的底部内容区域插槽,有时候你可能会用上', tableFooter: () => '表格的底部内容区域插槽,有时候你可能会用上',
}} }}
</RayTable> </RayTable>
</NLayout> </div>
) )
}, },
}) })