mirror of
https://github.com/vbenjs/vue-vben-admin.git
synced 2025-08-28 05:39:34 +08:00
feat: multi-language layout
This commit is contained in:
@@ -8,18 +8,21 @@ import { GithubFilled } from '@ant-design/icons-vue';
|
||||
import { DOC_URL, GITHUB_URL, SITE_URL } from '/@/settings/siteSetting';
|
||||
import { openWindow } from '/@/utils';
|
||||
|
||||
import { useI18n } from '/@/hooks/web/useI18n';
|
||||
|
||||
export default defineComponent({
|
||||
name: 'LayoutContent',
|
||||
setup() {
|
||||
const { t } = useI18n('layout.footer');
|
||||
return () => {
|
||||
return (
|
||||
<Layout.Footer class="layout-footer">
|
||||
{() => (
|
||||
<>
|
||||
<div class="layout-footer__links">
|
||||
<a onClick={() => openWindow(SITE_URL)}>在线预览</a>
|
||||
<a onClick={() => openWindow(SITE_URL)}>{t('onlinePreview')}</a>
|
||||
<GithubFilled onClick={() => openWindow(GITHUB_URL)} class="github" />
|
||||
<a onClick={() => openWindow(DOC_URL)}>在线文档</a>
|
||||
<a onClick={() => openWindow(DOC_URL)}>{t('onlineDocument')}</a>
|
||||
</div>
|
||||
<div>Copyright ©2020 Vben Admin</div>
|
||||
</>
|
||||
|
@@ -1,6 +1,7 @@
|
||||
import './index.less';
|
||||
|
||||
import type { FunctionalComponent } from 'vue';
|
||||
import type { Component } from '/@/components/types';
|
||||
|
||||
import { defineComponent, unref, computed, ref, nextTick } from 'vue';
|
||||
|
||||
@@ -27,6 +28,7 @@ import { useWindowSizeFn } from '/@/hooks/event/useWindowSizeFn';
|
||||
import { useHeaderSetting } from '/@/hooks/setting/useHeaderSetting';
|
||||
import { useMenuSetting } from '/@/hooks/setting/useMenuSetting';
|
||||
import { useRootSetting } from '/@/hooks/setting/useRootSetting';
|
||||
import { useLocaleSetting } from '/@/hooks/setting/useLocaleSetting';
|
||||
|
||||
import { useRouter } from 'vue-router';
|
||||
|
||||
@@ -34,7 +36,8 @@ import { errorStore } from '/@/store/modules/error';
|
||||
|
||||
import { PageEnum } from '/@/enums/pageEnum';
|
||||
import { MenuModeEnum, MenuSplitTyeEnum } from '/@/enums/menuEnum';
|
||||
import { Component } from '/@/components/types';
|
||||
import { AppLocalePicker } from '/@/components/Application';
|
||||
import { useI18n } from '/@/hooks/web/useI18n';
|
||||
|
||||
interface TooltipItemProps {
|
||||
title: string;
|
||||
@@ -65,9 +68,11 @@ export default defineComponent({
|
||||
const logoWidthRef = ref(200);
|
||||
const logoRef = ref<ComponentRef>(null);
|
||||
const { refreshPage } = useTabs();
|
||||
const { t } = useI18n('layout.header');
|
||||
|
||||
const { getShowTopMenu, getShowHeaderTrigger, getSplit, getTopMenuAlign } = useMenuSetting();
|
||||
|
||||
const { getShowLocale } = useLocaleSetting();
|
||||
const { getUseErrorHandle, getShowBreadCrumbIcon } = useRootSetting();
|
||||
|
||||
const {
|
||||
@@ -160,8 +165,8 @@ export default defineComponent({
|
||||
|
||||
function renderActionDefault(Comp: Component | any, event: Fn) {
|
||||
return (
|
||||
<div class={`layout-header__action-item`} onClick={event}>
|
||||
<Comp class={`layout-header__action-icon`} />
|
||||
<div class="layout-header__action-item" onClick={event}>
|
||||
<Comp class="layout-header__action-icon" />
|
||||
</div>
|
||||
);
|
||||
}
|
||||
@@ -170,7 +175,7 @@ export default defineComponent({
|
||||
return (
|
||||
<div class={`layout-header__action`}>
|
||||
{unref(getUseErrorHandle) && (
|
||||
<TooltipItem title="错误日志">
|
||||
<TooltipItem title={t('layout.header.tooltipErrorLog')}>
|
||||
{() => (
|
||||
<Badge
|
||||
count={errorStore.getErrorListCountState}
|
||||
@@ -185,23 +190,31 @@ export default defineComponent({
|
||||
)}
|
||||
|
||||
{unref(getUseLockPage) && (
|
||||
<TooltipItem title="锁定屏幕">
|
||||
<TooltipItem title={t('layout.header.tooltipLock')}>
|
||||
{() => renderActionDefault(LockOutlined, handleLockPage)}
|
||||
</TooltipItem>
|
||||
)}
|
||||
|
||||
{unref(getShowNotice) && (
|
||||
<TooltipItem title="消息通知">{() => <NoticeAction />}</TooltipItem>
|
||||
<TooltipItem title={t('layout.header.tooltipNotify')}>
|
||||
{() => <NoticeAction />}
|
||||
</TooltipItem>
|
||||
)}
|
||||
|
||||
{unref(getShowRedo) && (
|
||||
<TooltipItem title="刷新">
|
||||
<TooltipItem title={t('layout.header.tooltipRedo')}>
|
||||
{() => renderActionDefault(RedoOutlined, refreshPage)}
|
||||
</TooltipItem>
|
||||
)}
|
||||
|
||||
{unref(getShowFullScreen) && (
|
||||
<TooltipItem title={unref(isFullscreenRef) ? '退出全屏' : '全屏'}>
|
||||
<TooltipItem
|
||||
title={
|
||||
unref(isFullscreenRef)
|
||||
? t('layout.header.tooltipExitFull')
|
||||
: t('layout.header.tooltipEntryFull')
|
||||
}
|
||||
>
|
||||
{() => {
|
||||
const Icon = !unref(isFullscreenRef) ? (
|
||||
<FullscreenOutlined />
|
||||
@@ -212,7 +225,14 @@ export default defineComponent({
|
||||
}}
|
||||
</TooltipItem>
|
||||
)}
|
||||
<UserDropdown class={`layout-header__user-dropdown`} />
|
||||
<UserDropdown class="layout-header__user-dropdown" />
|
||||
{unref(getShowLocale) && (
|
||||
<AppLocalePicker
|
||||
reload={true}
|
||||
showText={false}
|
||||
class="layout-header__action-item locale"
|
||||
/>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
@@ -1,5 +1,5 @@
|
||||
// components
|
||||
import { Dropdown, Menu, Divider } from 'ant-design-vue';
|
||||
import { Dropdown, Menu } from 'ant-design-vue';
|
||||
|
||||
import { defineComponent, computed, unref } from 'vue';
|
||||
|
||||
@@ -16,6 +16,7 @@ import { openWindow } from '/@/utils';
|
||||
|
||||
import { useHeaderSetting } from '/@/hooks/setting/useHeaderSetting';
|
||||
import { FunctionalComponent } from 'vue';
|
||||
import { useI18n } from '/@/hooks/web/useI18n';
|
||||
|
||||
type MenuEvent = 'loginOut' | 'doc';
|
||||
interface MenuItemProps {
|
||||
@@ -43,6 +44,7 @@ const MenuItem: FunctionalComponent<MenuItemProps> = (props) => {
|
||||
export default defineComponent({
|
||||
name: 'UserDropdown',
|
||||
setup() {
|
||||
const { t } = useI18n('layout.header');
|
||||
const { getShowDoc } = useHeaderSetting();
|
||||
|
||||
const getUserInfo = computed(() => {
|
||||
@@ -89,9 +91,14 @@ export default defineComponent({
|
||||
<Menu onClick={handleMenuClick}>
|
||||
{() => (
|
||||
<>
|
||||
{showDoc && <MenuItem key="doc" text="文档" icon="gg:loadbar-doc" />}
|
||||
{showDoc && <Divider />}
|
||||
<MenuItem key="loginOut" text="退出系统" icon="ant-design:poweroff-outlined" />
|
||||
{showDoc && <MenuItem key="doc" text={t('dropdownItemDoc')} icon="gg:loadbar-doc" />}
|
||||
{/* @ts-ignore */}
|
||||
{showDoc && <Menu.Divider />}
|
||||
<MenuItem
|
||||
key="loginOut"
|
||||
text={t('dropdownItemLoginOut')}
|
||||
icon="ant-design:poweroff-outlined"
|
||||
/>
|
||||
</>
|
||||
)}
|
||||
</Menu>
|
||||
@@ -100,7 +107,7 @@ export default defineComponent({
|
||||
|
||||
return () => {
|
||||
return (
|
||||
<Dropdown placement="bottomLeft">
|
||||
<Dropdown placement="bottomLeft" overlayClassName="app-layout-header-user-dropdown-overlay">
|
||||
{{
|
||||
default: () => renderSlotsDefault(),
|
||||
overlay: () => renderSlotOverlay(),
|
||||
|
@@ -92,6 +92,11 @@
|
||||
&:hover {
|
||||
background: @header-light-bg-hover-color;
|
||||
}
|
||||
|
||||
&.locale {
|
||||
padding: 0 10px;
|
||||
color: rgba(0, 0, 0, 0.65);
|
||||
}
|
||||
}
|
||||
|
||||
&-icon {
|
||||
@@ -221,3 +226,9 @@
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.app-layout-header-user-dropdown-overlay {
|
||||
.ant-dropdown-menu-item {
|
||||
min-width: 160px;
|
||||
}
|
||||
}
|
||||
|
@@ -2,9 +2,10 @@
|
||||
|
||||
.default-layout {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
width: 100%;
|
||||
min-height: 100%;
|
||||
background: @content-bg;
|
||||
flex-direction: column;
|
||||
|
||||
> .ant-layout {
|
||||
min-height: 100%;
|
||||
|
@@ -9,11 +9,13 @@ import headerImg from '/@/assets/images/header.jpg';
|
||||
|
||||
import { appStore } from '/@/store/modules/app';
|
||||
import { userStore } from '/@/store/modules/user';
|
||||
import { useI18n } from '/@/hooks/web/useI18n';
|
||||
|
||||
const prefixCls = 'lock-modal';
|
||||
export default defineComponent({
|
||||
name: 'LockModal',
|
||||
setup(_, { attrs }) {
|
||||
const { t } = useI18n('layout.header');
|
||||
const [register, { closeModal }] = useModalInner();
|
||||
|
||||
const [registerForm, { validateFields, resetFields }] = useForm({
|
||||
@@ -21,7 +23,7 @@ export default defineComponent({
|
||||
schemas: [
|
||||
{
|
||||
field: 'password',
|
||||
label: '锁屏密码',
|
||||
label: t('lockScreenPassword'),
|
||||
component: 'InputPassword',
|
||||
required: true,
|
||||
},
|
||||
@@ -49,7 +51,13 @@ export default defineComponent({
|
||||
}
|
||||
|
||||
return () => (
|
||||
<BasicModal footer={null} title="锁定屏幕" {...attrs} class={prefixCls} onRegister={register}>
|
||||
<BasicModal
|
||||
footer={null}
|
||||
title={t('lockScreen')}
|
||||
{...attrs}
|
||||
class={prefixCls}
|
||||
onRegister={register}
|
||||
>
|
||||
{() => (
|
||||
<div class={`${prefixCls}__entry`}>
|
||||
<div class={`${prefixCls}__header`}>
|
||||
@@ -61,10 +69,10 @@ export default defineComponent({
|
||||
|
||||
<div class={`${prefixCls}__footer`}>
|
||||
<Button type="primary" block class="mt-2" onClick={lock}>
|
||||
{() => '锁屏'}
|
||||
{() => t('lockScreenBtn')}
|
||||
</Button>
|
||||
<Button block class="mt-2" onClick={lock.bind(null, false)}>
|
||||
{() => ' 不设置密码锁屏'}
|
||||
{() => t('notLockScreenPassword')}
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
|
@@ -13,6 +13,7 @@ import { useTabDropdown } from './useTabDropdown';
|
||||
import { useMenuSetting } from '/@/hooks/setting/useMenuSetting';
|
||||
import { useHeaderSetting } from '/@/hooks/setting/useHeaderSetting';
|
||||
import { useMultipleTabSetting } from '/@/hooks/setting/useMultipleTabSetting';
|
||||
import { useI18n } from '/@/hooks/web/useI18n';
|
||||
|
||||
const ExtraContent: FunctionalComponent = () => {
|
||||
return (
|
||||
@@ -56,6 +57,7 @@ export default defineComponent({
|
||||
},
|
||||
},
|
||||
setup(props) {
|
||||
const { t } = useI18n('layout.multipleTab');
|
||||
const { getShowMenu } = useMenuSetting();
|
||||
const { getShowHeader } = useHeaderSetting();
|
||||
const { getShowQuick } = useMultipleTabSetting();
|
||||
@@ -71,7 +73,10 @@ export default defineComponent({
|
||||
const { getDropMenuList, handleMenuEvent } = useTabDropdown(props as TabContentProps);
|
||||
|
||||
return () => {
|
||||
const scaleAction = getScaleAction(unref(getIsScale) ? '收起' : '展开', unref(getIsScale));
|
||||
const scaleAction = getScaleAction(
|
||||
unref(getIsScale) ? t('putAway') : t('unfold'),
|
||||
unref(getIsScale)
|
||||
);
|
||||
const dropMenuList = unref(getDropMenuList) || [];
|
||||
|
||||
const isTab = unref(getIsTab);
|
||||
|
@@ -2,6 +2,10 @@ import { DropMenu } from '/@/components/Dropdown/index';
|
||||
import { AppRouteRecordRaw } from '/@/router/types';
|
||||
import type { TabItem } from '/@/store/modules/tab';
|
||||
|
||||
import { useI18n } from '/@/hooks/web/useI18n';
|
||||
|
||||
const { t } = useI18n('layout.multipleTab');
|
||||
|
||||
export enum TabContentEnum {
|
||||
TAB_TYPE,
|
||||
EXTRA_TYPE,
|
||||
@@ -37,40 +41,40 @@ export function getActions() {
|
||||
const REFRESH_PAGE: DropMenu = {
|
||||
icon: 'ant-design:reload-outlined',
|
||||
event: MenuEventEnum.REFRESH_PAGE,
|
||||
text: '刷新',
|
||||
text: t('redo'),
|
||||
disabled: false,
|
||||
};
|
||||
const CLOSE_CURRENT: DropMenu = {
|
||||
icon: 'ant-design:close-outlined',
|
||||
event: MenuEventEnum.CLOSE_CURRENT,
|
||||
text: '关闭',
|
||||
text: t('close'),
|
||||
disabled: false,
|
||||
divider: true,
|
||||
};
|
||||
const CLOSE_LEFT: DropMenu = {
|
||||
icon: 'ant-design:pic-left-outlined',
|
||||
event: MenuEventEnum.CLOSE_LEFT,
|
||||
text: '关闭左侧',
|
||||
text: t('closeLeft'),
|
||||
disabled: false,
|
||||
divider: false,
|
||||
};
|
||||
const CLOSE_RIGHT: DropMenu = {
|
||||
icon: 'ant-design:pic-right-outlined',
|
||||
event: MenuEventEnum.CLOSE_RIGHT,
|
||||
text: '关闭右侧',
|
||||
text: t('closeRight'),
|
||||
disabled: false,
|
||||
divider: true,
|
||||
};
|
||||
const CLOSE_OTHER: DropMenu = {
|
||||
icon: 'ant-design:pic-center-outlined',
|
||||
event: MenuEventEnum.CLOSE_OTHER,
|
||||
text: '关闭其他',
|
||||
text: t('closeOther'),
|
||||
disabled: false,
|
||||
};
|
||||
const CLOSE_ALL: DropMenu = {
|
||||
icon: 'ant-design:line-outlined',
|
||||
event: MenuEventEnum.CLOSE_ALL,
|
||||
text: '关闭全部',
|
||||
text: t('closeAll'),
|
||||
disabled: false,
|
||||
};
|
||||
return [REFRESH_PAGE, CLOSE_CURRENT, CLOSE_LEFT, CLOSE_RIGHT, CLOSE_OTHER, CLOSE_ALL];
|
||||
|
@@ -18,6 +18,7 @@ import { useMenuSetting } from '/@/hooks/setting/useMenuSetting';
|
||||
import { useHeaderSetting } from '/@/hooks/setting/useHeaderSetting';
|
||||
import { useMultipleTabSetting } from '/@/hooks/setting/useMultipleTabSetting';
|
||||
import { useTransitionSetting } from '/@/hooks/setting/useTransitionSetting';
|
||||
import { useI18n } from '/@/hooks/web/useI18n';
|
||||
|
||||
import { updateColorWeak, updateGrayMode } from '/@/setup/theme';
|
||||
|
||||
@@ -55,6 +56,7 @@ interface ThemePickerProps {
|
||||
}
|
||||
|
||||
const { createSuccessModal, createMessage } = useMessage();
|
||||
const { t } = useI18n('layout.setting');
|
||||
|
||||
/**
|
||||
* Menu type Picker comp
|
||||
@@ -120,8 +122,8 @@ const FooterButton: FunctionalComponent = () => {
|
||||
const { isSuccessRef } = useCopyToClipboard(JSON.stringify(unref(getRootSetting), null, 2));
|
||||
unref(isSuccessRef) &&
|
||||
createSuccessModal({
|
||||
title: '操作成功',
|
||||
content: '复制成功,请到 src/settings/projectSetting.ts 中修改配置!',
|
||||
title: t('operatingTitle'),
|
||||
content: t('operatingContent'),
|
||||
});
|
||||
}
|
||||
function handleResetSetting() {
|
||||
@@ -131,7 +133,7 @@ const FooterButton: FunctionalComponent = () => {
|
||||
// updateTheme(themeColor);
|
||||
updateColorWeak(colorWeak);
|
||||
updateGrayMode(grayMode);
|
||||
createMessage.success('重置成功!');
|
||||
createMessage.success(t('resetSuccess'));
|
||||
} catch (error) {
|
||||
createMessage.error(error);
|
||||
}
|
||||
@@ -149,7 +151,7 @@ const FooterButton: FunctionalComponent = () => {
|
||||
{() => (
|
||||
<>
|
||||
<CopyOutlined class="mr-2" />
|
||||
拷贝
|
||||
{t('copyBtn')}
|
||||
</>
|
||||
)}
|
||||
</Button>
|
||||
@@ -157,7 +159,7 @@ const FooterButton: FunctionalComponent = () => {
|
||||
{() => (
|
||||
<>
|
||||
<RedoOutlined class="mr-2" />
|
||||
重置
|
||||
{t('resetBtn')}
|
||||
</>
|
||||
)}
|
||||
</Button>
|
||||
@@ -165,7 +167,7 @@ const FooterButton: FunctionalComponent = () => {
|
||||
{() => (
|
||||
<>
|
||||
<RedoOutlined class="mr-2" />
|
||||
清空缓存并返回登录页
|
||||
{t('clearBtn')}
|
||||
</>
|
||||
)}
|
||||
</Button>
|
||||
@@ -224,7 +226,7 @@ export default defineComponent({
|
||||
return (
|
||||
<>
|
||||
<MenuTypePicker />
|
||||
{renderSwitchItem('分割菜单', {
|
||||
{renderSwitchItem(t('splitMenu'), {
|
||||
handler: (e) => {
|
||||
baseHandler(HandlerEnum.MENU_SPLIT, e);
|
||||
},
|
||||
@@ -238,7 +240,7 @@ export default defineComponent({
|
||||
function renderTheme() {
|
||||
return (
|
||||
<>
|
||||
<Divider>{() => '顶栏主题'}</Divider>
|
||||
<Divider>{() => t('headerTheme')}</Divider>
|
||||
<ThemePicker
|
||||
colorList={HEADER_PRESET_BG_COLOR_LIST}
|
||||
def={unref(getHeaderBgColor)}
|
||||
@@ -246,7 +248,7 @@ export default defineComponent({
|
||||
baseHandler(HandlerEnum.HEADER_THEME, e);
|
||||
}}
|
||||
/>
|
||||
<Divider>{() => '菜单主题'}</Divider>
|
||||
<Divider>{() => t('sidebarTheme')}</Divider>
|
||||
<ThemePicker
|
||||
colorList={SIDE_BAR_BG_COLOR_LIST}
|
||||
def={unref(getMenuBgColor)}
|
||||
@@ -263,56 +265,56 @@ export default defineComponent({
|
||||
*/
|
||||
function renderFeatures() {
|
||||
return [
|
||||
renderSwitchItem('侧边菜单拖拽', {
|
||||
renderSwitchItem(t('menuDrag'), {
|
||||
handler: (e) => {
|
||||
baseHandler(HandlerEnum.MENU_HAS_DRAG, e);
|
||||
},
|
||||
def: unref(getCanDrag),
|
||||
disabled: !unref(getShowMenuRef),
|
||||
}),
|
||||
renderSwitchItem('侧边菜单搜索', {
|
||||
renderSwitchItem(t('menuSearch'), {
|
||||
handler: (e) => {
|
||||
baseHandler(HandlerEnum.MENU_SHOW_SEARCH, e);
|
||||
},
|
||||
def: unref(getShowSearch),
|
||||
disabled: !unref(getShowMenuRef),
|
||||
}),
|
||||
renderSwitchItem('侧边菜单手风琴模式', {
|
||||
renderSwitchItem(t('menuAccordion'), {
|
||||
handler: (e) => {
|
||||
baseHandler(HandlerEnum.MENU_ACCORDION, e);
|
||||
},
|
||||
def: unref(getAccordion),
|
||||
disabled: !unref(getShowMenuRef),
|
||||
}),
|
||||
renderSwitchItem('折叠菜单', {
|
||||
renderSwitchItem(t('menuCollapse'), {
|
||||
handler: (e) => {
|
||||
baseHandler(HandlerEnum.MENU_COLLAPSED, e);
|
||||
},
|
||||
def: unref(getCollapsed),
|
||||
disabled: !unref(getShowMenuRef),
|
||||
}),
|
||||
renderSwitchItem('折叠菜单显示名称', {
|
||||
renderSwitchItem(t('collapseMenuDisplayName'), {
|
||||
handler: (e) => {
|
||||
baseHandler(HandlerEnum.MENU_COLLAPSED_SHOW_TITLE, e);
|
||||
},
|
||||
def: unref(getCollapsedShowTitle),
|
||||
disabled: !unref(getShowMenuRef) || !unref(getCollapsed),
|
||||
}),
|
||||
renderSwitchItem('固定header', {
|
||||
renderSwitchItem(t('fixedHeader'), {
|
||||
handler: (e) => {
|
||||
baseHandler(HandlerEnum.HEADER_FIXED, e);
|
||||
},
|
||||
def: unref(getHeaderFixed),
|
||||
disabled: !unref(getShowHeader),
|
||||
}),
|
||||
renderSwitchItem('固定Siderbar', {
|
||||
renderSwitchItem(t('fixedSideBar'), {
|
||||
handler: (e) => {
|
||||
baseHandler(HandlerEnum.MENU_FIXED, e);
|
||||
},
|
||||
def: unref(getMenuFixed),
|
||||
disabled: !unref(getShowMenuRef),
|
||||
}),
|
||||
renderSelectItem('顶部菜单布局', {
|
||||
renderSelectItem(t('topMenuLayout'), {
|
||||
handler: (e) => {
|
||||
baseHandler(HandlerEnum.MENU_TOP_ALIGN, e);
|
||||
},
|
||||
@@ -320,7 +322,7 @@ export default defineComponent({
|
||||
options: topMenuAlignOptions,
|
||||
disabled: !unref(getShowHeader) || (!unref(getIsTopMenu) && !unref(getSplit)),
|
||||
}),
|
||||
renderSelectItem('菜单折叠按钮', {
|
||||
renderSelectItem(t('menuCollapseButton'), {
|
||||
handler: (e) => {
|
||||
baseHandler(HandlerEnum.MENU_TRIGGER, e);
|
||||
},
|
||||
@@ -329,7 +331,7 @@ export default defineComponent({
|
||||
options: menuTriggerOptions,
|
||||
}),
|
||||
|
||||
renderSelectItem('内容区域宽度', {
|
||||
renderSelectItem(t('contentMode'), {
|
||||
handler: (e) => {
|
||||
baseHandler(HandlerEnum.CONTENT_MODE, e);
|
||||
},
|
||||
@@ -337,9 +339,9 @@ export default defineComponent({
|
||||
options: contentModeOptions,
|
||||
}),
|
||||
<div class={`setting-drawer__cell-item`}>
|
||||
<span>自动锁屏</span>
|
||||
<span>{t('autoScreenLock')}</span>
|
||||
<InputNumber
|
||||
style="width:120px"
|
||||
style="width:126px"
|
||||
size="small"
|
||||
min={0}
|
||||
onChange={(e: any) => {
|
||||
@@ -348,16 +350,16 @@ export default defineComponent({
|
||||
defaultValue={appStore.getProjectConfig.lockTime}
|
||||
formatter={(value: string) => {
|
||||
if (parseInt(value) === 0) {
|
||||
return '0(不自动锁屏)';
|
||||
return `0(${t('notAutoScreenLock')})`;
|
||||
}
|
||||
return `${value}分钟`;
|
||||
return `${value}${t('minute')}`;
|
||||
}}
|
||||
/>
|
||||
</div>,
|
||||
<div class={`setting-drawer__cell-item`}>
|
||||
<span>菜单展开宽度</span>
|
||||
<span>{t('expandedMenuWidth')}</span>
|
||||
<InputNumber
|
||||
style="width:120px"
|
||||
style="width:126px"
|
||||
size="small"
|
||||
max={600}
|
||||
min={100}
|
||||
@@ -375,27 +377,27 @@ export default defineComponent({
|
||||
|
||||
function renderContent() {
|
||||
return [
|
||||
renderSwitchItem('面包屑', {
|
||||
renderSwitchItem(t('breadcrumb'), {
|
||||
handler: (e) => {
|
||||
baseHandler(HandlerEnum.SHOW_BREADCRUMB, e);
|
||||
},
|
||||
def: unref(getShowBreadCrumb),
|
||||
disabled: !unref(getShowHeader),
|
||||
}),
|
||||
renderSwitchItem('面包屑图标', {
|
||||
renderSwitchItem(t('breadcrumbIcon'), {
|
||||
handler: (e) => {
|
||||
baseHandler(HandlerEnum.SHOW_BREADCRUMB_ICON, e);
|
||||
},
|
||||
def: unref(getShowBreadCrumbIcon),
|
||||
disabled: !unref(getShowHeader),
|
||||
}),
|
||||
renderSwitchItem('标签页', {
|
||||
renderSwitchItem(t('tabs'), {
|
||||
handler: (e) => {
|
||||
baseHandler(HandlerEnum.TABS_SHOW, e);
|
||||
},
|
||||
def: unref(getShowMultipleTab),
|
||||
}),
|
||||
renderSwitchItem('标签页快捷按钮', {
|
||||
renderSwitchItem(t('tabsQuickBtn'), {
|
||||
handler: (e) => {
|
||||
baseHandler(HandlerEnum.TABS_SHOW_QUICK, e);
|
||||
},
|
||||
@@ -403,14 +405,14 @@ export default defineComponent({
|
||||
disabled: !unref(getShowMultipleTab),
|
||||
}),
|
||||
|
||||
renderSwitchItem('左侧菜单', {
|
||||
renderSwitchItem(t('sidebar'), {
|
||||
handler: (e) => {
|
||||
baseHandler(HandlerEnum.MENU_SHOW_SIDEBAR, e);
|
||||
},
|
||||
def: unref(getShowMenu),
|
||||
disabled: unref(getIsHorizontal),
|
||||
}),
|
||||
renderSwitchItem('顶栏', {
|
||||
renderSwitchItem(t('header'), {
|
||||
handler: (e) => {
|
||||
baseHandler(HandlerEnum.HEADER_SHOW, e);
|
||||
},
|
||||
@@ -422,25 +424,25 @@ export default defineComponent({
|
||||
},
|
||||
def: unref(getShowLogo),
|
||||
}),
|
||||
renderSwitchItem('页脚', {
|
||||
renderSwitchItem(t('footer'), {
|
||||
handler: (e) => {
|
||||
baseHandler(HandlerEnum.SHOW_FOOTER, e);
|
||||
},
|
||||
def: unref(getShowFooter),
|
||||
}),
|
||||
renderSwitchItem('全屏内容', {
|
||||
renderSwitchItem(t('fullContent'), {
|
||||
handler: (e) => {
|
||||
baseHandler(HandlerEnum.FULL_CONTENT, e);
|
||||
},
|
||||
def: unref(getFullContent),
|
||||
}),
|
||||
renderSwitchItem('灰色模式', {
|
||||
renderSwitchItem(t('grayMode'), {
|
||||
handler: (e) => {
|
||||
baseHandler(HandlerEnum.GRAY_MODE, e);
|
||||
},
|
||||
def: unref(getGrayMode),
|
||||
}),
|
||||
renderSwitchItem('色弱模式', {
|
||||
renderSwitchItem(t('colorWeak'), {
|
||||
handler: (e) => {
|
||||
baseHandler(HandlerEnum.COLOR_WEAK, e);
|
||||
},
|
||||
@@ -452,13 +454,13 @@ export default defineComponent({
|
||||
function renderTransition() {
|
||||
return (
|
||||
<>
|
||||
{renderSwitchItem('顶部进度条', {
|
||||
{renderSwitchItem(t('progress'), {
|
||||
handler: (e) => {
|
||||
baseHandler(HandlerEnum.OPEN_PROGRESS, e);
|
||||
},
|
||||
def: unref(getOpenNProgress),
|
||||
})}
|
||||
{renderSwitchItem('切换loading', {
|
||||
{renderSwitchItem(t('switchLoading'), {
|
||||
handler: (e) => {
|
||||
baseHandler(HandlerEnum.OPEN_PAGE_LOADING, e);
|
||||
},
|
||||
@@ -466,14 +468,14 @@ export default defineComponent({
|
||||
disabled: !unref(getEnableTransition),
|
||||
})}
|
||||
|
||||
{renderSwitchItem('切换动画', {
|
||||
{renderSwitchItem(t('switchAnimation'), {
|
||||
handler: (e) => {
|
||||
baseHandler(HandlerEnum.OPEN_ROUTE_TRANSITION, e);
|
||||
},
|
||||
def: unref(getEnableTransition),
|
||||
})}
|
||||
|
||||
{renderSelectItem('动画类型', {
|
||||
{renderSelectItem(t('animationType'), {
|
||||
handler: (e) => {
|
||||
baseHandler(HandlerEnum.ROUTER_TRANSITION, e);
|
||||
},
|
||||
@@ -495,7 +497,7 @@ export default defineComponent({
|
||||
{...opt}
|
||||
disabled={disabled}
|
||||
size="small"
|
||||
style={{ width: '120px' }}
|
||||
style={{ width: '126px' }}
|
||||
onChange={(e) => {
|
||||
handler && handler(e);
|
||||
}}
|
||||
@@ -517,26 +519,26 @@ export default defineComponent({
|
||||
onChange={(e: any) => {
|
||||
handler && handler(e);
|
||||
}}
|
||||
checkedChildren="开"
|
||||
unCheckedChildren="关"
|
||||
checkedChildren={t('on')}
|
||||
unCheckedChildren={t('off')}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
return () => (
|
||||
<BasicDrawer {...attrs} title="项目配置" width={300} wrapClassName="setting-drawer">
|
||||
<BasicDrawer {...attrs} title={t('drawerTitle')} width={330} wrapClassName="setting-drawer">
|
||||
{{
|
||||
default: () => (
|
||||
<>
|
||||
<Divider>{() => '导航栏模式'}</Divider>
|
||||
<Divider>{() => t('navMode')}</Divider>
|
||||
{renderSidebar()}
|
||||
{renderTheme()}
|
||||
<Divider>{() => '界面功能'}</Divider>
|
||||
<Divider>{() => t('interfaceFunction')}</Divider>
|
||||
{renderFeatures()}
|
||||
<Divider>{() => '界面显示'}</Divider>
|
||||
<Divider>{() => t('interfaceDisplay')}</Divider>
|
||||
{renderContent()}
|
||||
<Divider>{() => '切换动画'}</Divider>
|
||||
<Divider>{() => t('animation')}</Divider>
|
||||
{renderTransition()}
|
||||
<Divider />
|
||||
<FooterButton />
|
||||
|
@@ -1,9 +1,12 @@
|
||||
import { ContentEnum, RouterTransitionEnum, ThemeEnum } from '/@/enums/appEnum';
|
||||
import { ContentEnum, RouterTransitionEnum } from '/@/enums/appEnum';
|
||||
import { MenuModeEnum, MenuTypeEnum, TopMenuAlignEnum, TriggerEnum } from '/@/enums/menuEnum';
|
||||
|
||||
import mixImg from '/@/assets/images/layout/menu-mix.svg';
|
||||
import sidebarImg from '/@/assets/images/layout/menu-sidebar.svg';
|
||||
import menuTopImg from '/@/assets/images/layout/menu-top.svg';
|
||||
import { useI18n } from '/@/hooks/web/useI18n';
|
||||
|
||||
const { t } = useI18n('layout.setting');
|
||||
|
||||
export enum HandlerEnum {
|
||||
CHANGE_LAYOUT,
|
||||
@@ -45,55 +48,44 @@ export enum HandlerEnum {
|
||||
OPEN_ROUTE_TRANSITION,
|
||||
}
|
||||
|
||||
export const themeOptions = [
|
||||
{
|
||||
value: ThemeEnum.LIGHT,
|
||||
label: '亮色',
|
||||
},
|
||||
{
|
||||
value: ThemeEnum.DARK,
|
||||
label: '暗色',
|
||||
},
|
||||
];
|
||||
|
||||
export const contentModeOptions = [
|
||||
{
|
||||
value: ContentEnum.FULL,
|
||||
label: '流式',
|
||||
label: t('contentModeFull'),
|
||||
},
|
||||
{
|
||||
value: ContentEnum.FIXED,
|
||||
label: '定宽',
|
||||
label: t('contentModeFixed'),
|
||||
},
|
||||
];
|
||||
|
||||
export const topMenuAlignOptions = [
|
||||
{
|
||||
value: TopMenuAlignEnum.CENTER,
|
||||
label: '居中',
|
||||
label: t('topMenuAlignRight'),
|
||||
},
|
||||
{
|
||||
value: TopMenuAlignEnum.START,
|
||||
label: '居左',
|
||||
label: t('topMenuAlignLeft'),
|
||||
},
|
||||
{
|
||||
value: TopMenuAlignEnum.END,
|
||||
label: '居右',
|
||||
label: t('topMenuAlignCenter'),
|
||||
},
|
||||
];
|
||||
|
||||
export const menuTriggerOptions = [
|
||||
{
|
||||
value: TriggerEnum.NONE,
|
||||
label: '不显示',
|
||||
label: t('menuTriggerNone'),
|
||||
},
|
||||
{
|
||||
value: TriggerEnum.FOOTER,
|
||||
label: '底部',
|
||||
label: t('menuTriggerBottom'),
|
||||
},
|
||||
{
|
||||
value: TriggerEnum.HEADER,
|
||||
label: '顶部',
|
||||
label: t('menuTriggerTop'),
|
||||
},
|
||||
];
|
||||
|
||||
@@ -112,20 +104,20 @@ export const routerTransitionOptions = [
|
||||
|
||||
export const menuTypeList = [
|
||||
{
|
||||
title: '左侧菜单模式',
|
||||
title: t('menuTypeSidebar'),
|
||||
mode: MenuModeEnum.INLINE,
|
||||
type: MenuTypeEnum.SIDEBAR,
|
||||
src: sidebarImg,
|
||||
},
|
||||
{
|
||||
title: '混合模式',
|
||||
title: t('menuTypeMix'),
|
||||
mode: MenuModeEnum.INLINE,
|
||||
type: MenuTypeEnum.MIX,
|
||||
src: mixImg,
|
||||
},
|
||||
|
||||
{
|
||||
title: '顶部菜单模式',
|
||||
title: t('menuTypeTopMenu'),
|
||||
mode: MenuModeEnum.HORIZONTAL,
|
||||
type: MenuTypeEnum.TOP_MENU,
|
||||
src: menuTopImg,
|
||||
|
@@ -1,6 +1,6 @@
|
||||
import './index.less';
|
||||
|
||||
import { computed, defineComponent, ref, unref, watch, nextTick } from 'vue';
|
||||
import { computed, defineComponent, ref, unref, watch, nextTick, CSSProperties } from 'vue';
|
||||
|
||||
import { Layout } from 'ant-design-vue';
|
||||
import LayoutMenu from '../menu';
|
||||
@@ -91,17 +91,19 @@ export default defineComponent({
|
||||
}
|
||||
);
|
||||
|
||||
const getHiddenDomStyle = computed(() => {
|
||||
const width = `${unref(getRealWidth)}px`;
|
||||
return {
|
||||
width: width,
|
||||
overflow: 'hidden',
|
||||
flex: `0 0 ${width}`,
|
||||
'max-width': width,
|
||||
'min-width': width,
|
||||
transition: 'all 0.2s',
|
||||
};
|
||||
});
|
||||
const getHiddenDomStyle = computed(
|
||||
(): CSSProperties => {
|
||||
const width = `${unref(getRealWidth)}px`;
|
||||
return {
|
||||
width: width,
|
||||
overflow: 'hidden',
|
||||
flex: `0 0 ${width}`,
|
||||
maxWidth: width,
|
||||
minWidth: width,
|
||||
transition: 'all 0.2s',
|
||||
};
|
||||
}
|
||||
);
|
||||
|
||||
function renderDefault() {
|
||||
return (
|
||||
|
Reference in New Issue
Block a user