21 changed files with 264 additions and 373 deletions
@ -1,30 +0,0 @@ |
|||
.lock-modal { |
|||
&__entry { |
|||
position: relative; |
|||
height: 240px; |
|||
padding: 130px 30px 60px 30px; |
|||
background: #fff; |
|||
border-radius: 10px; |
|||
} |
|||
|
|||
&__header { |
|||
position: absolute; |
|||
top: 0; |
|||
left: calc(50% - 45px); |
|||
width: auto; |
|||
text-align: center; |
|||
|
|||
&-img { |
|||
width: 70px; |
|||
border-radius: 50%; |
|||
} |
|||
|
|||
&-name { |
|||
margin-top: 5px; |
|||
} |
|||
} |
|||
|
|||
&__footer { |
|||
text-align: center; |
|||
} |
|||
} |
|||
@ -1,72 +0,0 @@ |
|||
import './LockAction.less'; |
|||
|
|||
import { defineComponent } from 'vue'; |
|||
import { BasicModal, useModalInner } from '/@/components/Modal/index'; |
|||
import { Button } from '/@/components/Button'; |
|||
import { BasicForm, useForm } from '/@/components/Form/index'; |
|||
|
|||
import headerImg from '/@/assets/images/header.jpg'; |
|||
|
|||
import { userStore } from '/@/store/modules/user'; |
|||
import { useI18n } from '/@/hooks/web/useI18n'; |
|||
import { lockStore } from '/@/store/modules/lock'; |
|||
|
|||
const prefixCls = 'lock-modal'; |
|||
export default defineComponent({ |
|||
name: 'LockModal', |
|||
setup(_, { attrs }) { |
|||
const { t } = useI18n(); |
|||
const [register, { closeModal }] = useModalInner(); |
|||
|
|||
const [registerForm, { validateFields, resetFields }] = useForm({ |
|||
showActionButtonGroup: false, |
|||
schemas: [ |
|||
{ |
|||
field: 'password', |
|||
label: t('layout.header.lockScreenPassword'), |
|||
component: 'InputPassword', |
|||
required: true, |
|||
}, |
|||
], |
|||
}); |
|||
|
|||
async function lock() { |
|||
const values = (await validateFields()) as any; |
|||
const password: string | undefined = values.password; |
|||
closeModal(); |
|||
|
|||
lockStore.commitLockInfoState({ |
|||
isLock: true, |
|||
pwd: password, |
|||
}); |
|||
await resetFields(); |
|||
} |
|||
|
|||
return () => ( |
|||
<BasicModal |
|||
footer={null} |
|||
title={t('layout.header.lockScreen')} |
|||
{...attrs} |
|||
class={prefixCls} |
|||
onRegister={register} |
|||
> |
|||
{() => ( |
|||
<div class={`${prefixCls}__entry`}> |
|||
<div class={`${prefixCls}__header`}> |
|||
<img src={headerImg} class={`${prefixCls}__header-img`} /> |
|||
<p class={`${prefixCls}__header-name`}>{userStore.getUserInfoState.realName}</p> |
|||
</div> |
|||
|
|||
<BasicForm onRegister={registerForm} /> |
|||
|
|||
<div class={`${prefixCls}__footer`}> |
|||
<Button type="primary" block class="mt-2" onClick={lock}> |
|||
{() => t('layout.header.lockScreenBtn')} |
|||
</Button> |
|||
</div> |
|||
</div> |
|||
)} |
|||
</BasicModal> |
|||
); |
|||
}, |
|||
}); |
|||
@ -1,38 +0,0 @@ |
|||
<template> |
|||
<span @click="handleLock"> |
|||
<Tooltip :title="t('layout.header.tooltipLock')" placement="bottom" :mouseEnterDelay="0.5"> |
|||
<LockOutlined /> |
|||
</Tooltip> |
|||
<LockAction @register="register" /> |
|||
</span> |
|||
</template> |
|||
<script lang="ts"> |
|||
import { defineComponent } from 'vue'; |
|||
import { Tooltip } from 'ant-design-vue'; |
|||
import { useI18n } from '/@/hooks/web/useI18n'; |
|||
import { LockOutlined } from '@ant-design/icons-vue'; |
|||
import { useModal } from '/@/components/Modal'; |
|||
import { createAsyncComponent } from '/@/utils/factory/createAsyncComponent'; |
|||
export default defineComponent({ |
|||
name: 'FullScreen', |
|||
components: { |
|||
LockOutlined, |
|||
Tooltip, |
|||
LockAction: createAsyncComponent(() => import('./LockModal.vue')), |
|||
}, |
|||
|
|||
setup() { |
|||
const { t } = useI18n(); |
|||
const [register, { openModal }] = useModal(); |
|||
|
|||
function handleLock() { |
|||
openModal(true); |
|||
} |
|||
return { |
|||
t, |
|||
register, |
|||
handleLock, |
|||
}; |
|||
}, |
|||
}); |
|||
</script> |
|||
@ -1,22 +0,0 @@ |
|||
@prefix-cls: ~'@{namespace}-layout-menu'; |
|||
@logo-prefix-cls: ~'@{namespace}-app-logo'; |
|||
|
|||
.@{prefix-cls} { |
|||
&-logo { |
|||
height: @header-height; |
|||
padding: 10px 4px 10px 10px; |
|||
|
|||
img { |
|||
width: @logo-width; |
|||
height: @logo-width; |
|||
} |
|||
} |
|||
|
|||
&--mobile { |
|||
.@{logo-prefix-cls} { |
|||
&__title { |
|||
opacity: 1; |
|||
} |
|||
} |
|||
} |
|||
} |
|||
@ -1,172 +0,0 @@ |
|||
import './index.less'; |
|||
|
|||
import type { PropType, CSSProperties } from 'vue'; |
|||
|
|||
import { computed, defineComponent, unref, toRef } from 'vue'; |
|||
import { BasicMenu } from '/@/components/Menu'; |
|||
import { SimpleMenu } from '/@/components/SimpleMenu'; |
|||
import { AppLogo } from '/@/components/Application'; |
|||
|
|||
import { MenuModeEnum, MenuSplitTyeEnum } from '/@/enums/menuEnum'; |
|||
|
|||
import { useMenuSetting } from '/@/hooks/setting/useMenuSetting'; |
|||
import { ScrollContainer } from '/@/components/Container'; |
|||
|
|||
import { useGo } from '/@/hooks/web/usePage'; |
|||
import { useSplitMenu } from './useLayoutMenu'; |
|||
import { openWindow } from '/@/utils'; |
|||
import { propTypes } from '/@/utils/propTypes'; |
|||
import { isUrl } from '/@/utils/is'; |
|||
import { useRootSetting } from '/@/hooks/setting/useRootSetting'; |
|||
import { useAppInject } from '/@/hooks/web/useAppInject'; |
|||
import { useDesign } from '/@/hooks/web/useDesign'; |
|||
|
|||
export default defineComponent({ |
|||
name: 'LayoutMenu', |
|||
props: { |
|||
theme: propTypes.oneOf(['light', 'dark']), |
|||
|
|||
splitType: { |
|||
type: Number as PropType<MenuSplitTyeEnum>, |
|||
default: MenuSplitTyeEnum.NONE, |
|||
}, |
|||
|
|||
isHorizontal: propTypes.bool, |
|||
// menu Mode
|
|||
menuMode: { |
|||
type: [String] as PropType<Nullable<MenuModeEnum>>, |
|||
default: '', |
|||
}, |
|||
}, |
|||
setup(props) { |
|||
const go = useGo(); |
|||
|
|||
const { |
|||
getMenuMode, |
|||
getMenuType, |
|||
getMenuTheme, |
|||
getCollapsed, |
|||
getCollapsedShowTitle, |
|||
getAccordion, |
|||
getIsHorizontal, |
|||
getIsSidebarType, |
|||
} = useMenuSetting(); |
|||
const { getShowLogo } = useRootSetting(); |
|||
|
|||
const { prefixCls } = useDesign('layout-menu'); |
|||
|
|||
const { menusRef } = useSplitMenu(toRef(props, 'splitType')); |
|||
|
|||
const { getIsMobile } = useAppInject(); |
|||
|
|||
const getComputedMenuMode = computed(() => |
|||
unref(getIsMobile) ? MenuModeEnum.INLINE : props.menuMode || unref(getMenuMode) |
|||
); |
|||
|
|||
const getComputedMenuTheme = computed(() => props.theme || unref(getMenuTheme)); |
|||
|
|||
const getIsShowLogo = computed(() => unref(getShowLogo) && unref(getIsSidebarType)); |
|||
|
|||
const getUseScroll = computed(() => { |
|||
return ( |
|||
!unref(getIsHorizontal) && |
|||
(unref(getIsSidebarType) || |
|||
props.splitType === MenuSplitTyeEnum.LEFT || |
|||
props.splitType === MenuSplitTyeEnum.NONE) |
|||
); |
|||
}); |
|||
|
|||
const getWrapperStyle = computed( |
|||
(): CSSProperties => { |
|||
return { |
|||
height: `calc(100% - ${unref(getIsShowLogo) ? '48px' : '0px'})`, |
|||
}; |
|||
} |
|||
); |
|||
|
|||
const getLogoClass = computed(() => { |
|||
return [ |
|||
`${prefixCls}-logo`, |
|||
unref(getComputedMenuTheme), |
|||
{ |
|||
[`${prefixCls}--mobile`]: unref(getIsMobile), |
|||
}, |
|||
]; |
|||
}); |
|||
/** |
|||
* click menu |
|||
* @param menu |
|||
*/ |
|||
|
|||
function handleMenuClick(path: string) { |
|||
go(path); |
|||
} |
|||
|
|||
/** |
|||
* before click menu |
|||
* @param menu |
|||
*/ |
|||
async function beforeMenuClickFn(path: string) { |
|||
if (!isUrl(path)) { |
|||
return true; |
|||
} |
|||
openWindow(path); |
|||
return false; |
|||
} |
|||
|
|||
function renderHeader() { |
|||
if (!unref(getIsShowLogo) && !unref(getIsMobile)) return null; |
|||
|
|||
return ( |
|||
<AppLogo |
|||
showTitle={!unref(getCollapsed)} |
|||
class={unref(getLogoClass)} |
|||
theme={unref(getComputedMenuTheme)} |
|||
/> |
|||
); |
|||
} |
|||
|
|||
function renderMenu() { |
|||
const menus = unref(menusRef); |
|||
// console.log(menus);
|
|||
if (!menus || !menus.length) return null; |
|||
return !props.isHorizontal ? ( |
|||
<SimpleMenu |
|||
beforeClickFn={beforeMenuClickFn} |
|||
items={menus} |
|||
theme={unref(getComputedMenuTheme)} |
|||
accordion={unref(getAccordion)} |
|||
collapse={unref(getCollapsed)} |
|||
collapsedShowTitle={unref(getCollapsedShowTitle)} |
|||
onMenuClick={handleMenuClick} |
|||
/> |
|||
) : ( |
|||
<BasicMenu |
|||
beforeClickFn={beforeMenuClickFn} |
|||
isHorizontal={props.isHorizontal} |
|||
type={unref(getMenuType)} |
|||
collapsedShowTitle={unref(getCollapsedShowTitle)} |
|||
showLogo={unref(getIsShowLogo)} |
|||
mode={unref(getComputedMenuMode)} |
|||
theme={unref(getComputedMenuTheme)} |
|||
items={menus} |
|||
accordion={unref(getAccordion)} |
|||
onMenuClick={handleMenuClick} |
|||
/> |
|||
); |
|||
} |
|||
|
|||
return () => { |
|||
return ( |
|||
<> |
|||
{renderHeader()} |
|||
{unref(getUseScroll) ? ( |
|||
<ScrollContainer style={unref(getWrapperStyle)}>{() => renderMenu()}</ScrollContainer> |
|||
) : ( |
|||
renderMenu() |
|||
)} |
|||
</> |
|||
); |
|||
}; |
|||
}, |
|||
}); |
|||
@ -0,0 +1,196 @@ |
|||
<script lang="tsx"> |
|||
import type { PropType, CSSProperties } from 'vue'; |
|||
|
|||
import { computed, defineComponent, unref, toRef } from 'vue'; |
|||
import { BasicMenu } from '/@/components/Menu'; |
|||
import { SimpleMenu } from '/@/components/SimpleMenu'; |
|||
import { AppLogo } from '/@/components/Application'; |
|||
|
|||
import { MenuModeEnum, MenuSplitTyeEnum } from '/@/enums/menuEnum'; |
|||
|
|||
import { useMenuSetting } from '/@/hooks/setting/useMenuSetting'; |
|||
import { ScrollContainer } from '/@/components/Container'; |
|||
|
|||
import { useGo } from '/@/hooks/web/usePage'; |
|||
import { useSplitMenu } from './useLayoutMenu'; |
|||
import { openWindow } from '/@/utils'; |
|||
import { propTypes } from '/@/utils/propTypes'; |
|||
import { isUrl } from '/@/utils/is'; |
|||
import { useRootSetting } from '/@/hooks/setting/useRootSetting'; |
|||
import { useAppInject } from '/@/hooks/web/useAppInject'; |
|||
import { useDesign } from '/@/hooks/web/useDesign'; |
|||
|
|||
export default defineComponent({ |
|||
name: 'LayoutMenu', |
|||
props: { |
|||
theme: propTypes.oneOf(['light', 'dark']), |
|||
|
|||
splitType: { |
|||
type: Number as PropType<MenuSplitTyeEnum>, |
|||
default: MenuSplitTyeEnum.NONE, |
|||
}, |
|||
|
|||
isHorizontal: propTypes.bool, |
|||
// menu Mode |
|||
menuMode: { |
|||
type: [String] as PropType<Nullable<MenuModeEnum>>, |
|||
default: '', |
|||
}, |
|||
}, |
|||
setup(props) { |
|||
const go = useGo(); |
|||
|
|||
const { |
|||
getMenuMode, |
|||
getMenuType, |
|||
getMenuTheme, |
|||
getCollapsed, |
|||
getCollapsedShowTitle, |
|||
getAccordion, |
|||
getIsHorizontal, |
|||
getIsSidebarType, |
|||
} = useMenuSetting(); |
|||
const { getShowLogo } = useRootSetting(); |
|||
|
|||
const { prefixCls } = useDesign('layout-menu'); |
|||
|
|||
const { menusRef } = useSplitMenu(toRef(props, 'splitType')); |
|||
|
|||
const { getIsMobile } = useAppInject(); |
|||
|
|||
const getComputedMenuMode = computed(() => |
|||
unref(getIsMobile) ? MenuModeEnum.INLINE : props.menuMode || unref(getMenuMode) |
|||
); |
|||
|
|||
const getComputedMenuTheme = computed(() => props.theme || unref(getMenuTheme)); |
|||
|
|||
const getIsShowLogo = computed(() => unref(getShowLogo) && unref(getIsSidebarType)); |
|||
|
|||
const getUseScroll = computed(() => { |
|||
return ( |
|||
!unref(getIsHorizontal) && |
|||
(unref(getIsSidebarType) || |
|||
props.splitType === MenuSplitTyeEnum.LEFT || |
|||
props.splitType === MenuSplitTyeEnum.NONE) |
|||
); |
|||
}); |
|||
|
|||
const getWrapperStyle = computed( |
|||
(): CSSProperties => { |
|||
return { |
|||
height: `calc(100% - ${unref(getIsShowLogo) ? '48px' : '0px'})`, |
|||
}; |
|||
} |
|||
); |
|||
|
|||
const getLogoClass = computed(() => { |
|||
return [ |
|||
`${prefixCls}-logo`, |
|||
unref(getComputedMenuTheme), |
|||
{ |
|||
[`${prefixCls}--mobile`]: unref(getIsMobile), |
|||
}, |
|||
]; |
|||
}); |
|||
/** |
|||
* click menu |
|||
* @param menu |
|||
*/ |
|||
|
|||
function handleMenuClick(path: string) { |
|||
go(path); |
|||
} |
|||
|
|||
/** |
|||
* before click menu |
|||
* @param menu |
|||
*/ |
|||
async function beforeMenuClickFn(path: string) { |
|||
if (!isUrl(path)) { |
|||
return true; |
|||
} |
|||
openWindow(path); |
|||
return false; |
|||
} |
|||
|
|||
function renderHeader() { |
|||
if (!unref(getIsShowLogo) && !unref(getIsMobile)) return null; |
|||
|
|||
return ( |
|||
<AppLogo |
|||
showTitle={!unref(getCollapsed)} |
|||
class={unref(getLogoClass)} |
|||
theme={unref(getComputedMenuTheme)} |
|||
/> |
|||
); |
|||
} |
|||
|
|||
function renderMenu() { |
|||
const menus = unref(menusRef); |
|||
// console.log(menus); |
|||
if (!menus || !menus.length) return null; |
|||
return !props.isHorizontal ? ( |
|||
<SimpleMenu |
|||
beforeClickFn={beforeMenuClickFn} |
|||
items={menus} |
|||
theme={unref(getComputedMenuTheme)} |
|||
accordion={unref(getAccordion)} |
|||
collapse={unref(getCollapsed)} |
|||
collapsedShowTitle={unref(getCollapsedShowTitle)} |
|||
onMenuClick={handleMenuClick} |
|||
/> |
|||
) : ( |
|||
<BasicMenu |
|||
beforeClickFn={beforeMenuClickFn} |
|||
isHorizontal={props.isHorizontal} |
|||
type={unref(getMenuType)} |
|||
collapsedShowTitle={unref(getCollapsedShowTitle)} |
|||
showLogo={unref(getIsShowLogo)} |
|||
mode={unref(getComputedMenuMode)} |
|||
theme={unref(getComputedMenuTheme)} |
|||
items={menus} |
|||
accordion={unref(getAccordion)} |
|||
onMenuClick={handleMenuClick} |
|||
/> |
|||
); |
|||
} |
|||
|
|||
return () => { |
|||
return ( |
|||
<> |
|||
{renderHeader()} |
|||
{unref(getUseScroll) ? ( |
|||
<ScrollContainer style={unref(getWrapperStyle)}>{() => renderMenu()}</ScrollContainer> |
|||
) : ( |
|||
renderMenu() |
|||
)} |
|||
</> |
|||
); |
|||
}; |
|||
}, |
|||
}); |
|||
</script> |
|||
<style lang="less"> |
|||
@prefix-cls: ~'@{namespace}-layout-menu'; |
|||
@logo-prefix-cls: ~'@{namespace}-app-logo'; |
|||
|
|||
.@{prefix-cls} { |
|||
&-logo { |
|||
height: @header-height; |
|||
padding: 10px 4px 10px 10px; |
|||
|
|||
img { |
|||
width: @logo-width; |
|||
height: @logo-width; |
|||
} |
|||
} |
|||
|
|||
&--mobile { |
|||
.@{logo-prefix-cls} { |
|||
&__title { |
|||
opacity: 1; |
|||
} |
|||
} |
|||
} |
|||
} |
|||
</style> |
|||
@ -1,3 +1,4 @@ |
|||
export default { |
|||
login: 'Login', |
|||
errorLogList: 'Error Log', |
|||
}; |
|||
|
|||
@ -1,3 +1,4 @@ |
|||
export default { |
|||
login: '登录', |
|||
errorLogList: '错误日志列表', |
|||
}; |
|||
|
|||
Loading…
Reference in new issue