Skip to content

Commit

Permalink
feat: support mobile layout adaptation
Browse files Browse the repository at this point in the history
  • Loading branch information
anncwb committed Dec 15, 2020
1 parent 683d1f5 commit c774a6d
Show file tree
Hide file tree
Showing 35 changed files with 589 additions and 630 deletions.
4 changes: 4 additions & 0 deletions CHANGELOG.zh_CN.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,17 +3,21 @@
### ✨ Features

- 移除左侧菜单搜索,新增顶部菜单搜索功能
- layout 移动端适配。页面未适配

### ⚡ Performance Improvements

- 异步引入组件
- 优化整体结构
- 替换菜单默认滚动条为滚动组件
- 菜单性能优化

### 🎫 Chores

- 返回顶部样式调整,避免遮住其他元素
- 升级`ant-design-vue``2.0.0-rc.5`
- 刷新按钮布局调整
- `route.meta` 移除 `externalLink` 属性

### 🐛 Bug Fixes

Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@
"sortablejs": "^1.12.0",
"vditor": "^3.7.2",
"vue": "^3.0.4",
"vue-i18n": "^9.0.0-beta.12",
"vue-i18n": "^9.0.0-beta.13",
"vue-router": "^4.0.1",
"vue-types": "^3.0.1",
"vuex": "^4.0.0-rc.2",
Expand Down
6 changes: 2 additions & 4 deletions src/components/Application/src/search/AppSearch.vue
Original file line number Diff line number Diff line change
@@ -1,13 +1,11 @@
<template>
<div :class="prefixCls" v-if="getShowSearch" @click="handleSearch">
<div :class="prefixCls" v-if="getShowSearch" @click.stop="handleSearch">
<Tooltip>
<template #title> {{ t('component.app.search') }} </template>
<SearchOutlined />
</Tooltip>

<transition name="zoom-fade" mode="out-in">
<AppSearchModal @close="handleClose" v-if="showModal" />
</transition>
<AppSearchModal @close="handleClose" :visible="showModal" />
</div>
</template>
<script lang="ts">
Expand Down
164 changes: 119 additions & 45 deletions src/components/Application/src/search/AppSearchModal.vue
Original file line number Diff line number Diff line change
@@ -1,48 +1,58 @@
<template>
<div :class="prefixCls" @click.stop>
<ClickOutSide @clickOutside="handleClose">
<div :class="`${prefixCls}-content`">
<a-input
:class="`${prefixCls}-input`"
:placeholder="t('component.app.search')"
allow-clear
@change="handleSearch"
>
<template #prefix>
<SearchOutlined />
</template>
</a-input>
<div :class="`${prefixCls}-not-data`" v-show="getIsNotData">
{{ t('component.app.searchNotData') }}
</div>
<ul :class="`${prefixCls}-list`" v-show="!getIsNotData" ref="scrollWrap">
<li
:ref="setRefs(index)"
v-for="(item, index) in searchResult"
:key="item.path"
:data-index="index"
@mouseenter="handleMouseenter"
@click="handleEnter"
:class="[
`${prefixCls}-list__item`,
{
[`${prefixCls}-list__item--active`]: activeIndex === index,
},
]"
>
<div :class="`${prefixCls}-list__item-icon`">
<g-icon :icon="item.icon || 'mdi:form-select'" :size="20" />
<Teleport to="body">
<transition name="zoom-fade" mode="out-in">
<div :class="getClass" @click.stop v-if="visible">
<ClickOutSide @clickOutside="handleClose">
<div :class="`${prefixCls}-content`">
<div :class="`${prefixCls}-input__wrapper`">
<a-input
:class="`${prefixCls}-input`"
:placeholder="t('component.app.search')"
allow-clear
@change="handleSearch"
>
<template #prefix>
<SearchOutlined />
</template>
</a-input>
<span :class="`${prefixCls}-cancel`" @click="handleClose">{{
t('component.app.cancel')
}}</span>
</div>
<div :class="`${prefixCls}-list__item-text`">{{ item.name }}</div>
<div :class="`${prefixCls}-list__item-enter`">
<g-icon icon="ant-design:enter-outlined" :size="20" />

<div :class="`${prefixCls}-not-data`" v-show="getIsNotData">
{{ t('component.app.searchNotData') }}
</div>
</li>
</ul>
<AppSearchFooter />
<ul :class="`${prefixCls}-list`" v-show="!getIsNotData" ref="scrollWrap">
<li
:ref="setRefs(index)"
v-for="(item, index) in searchResult"
:key="item.path"
:data-index="index"
@mouseenter="handleMouseenter"
@click="handleEnter"
:class="[
`${prefixCls}-list__item`,
{
[`${prefixCls}-list__item--active`]: activeIndex === index,
},
]"
>
<div :class="`${prefixCls}-list__item-icon`">
<g-icon :icon="item.icon || 'mdi:form-select'" :size="20" />
</div>
<div :class="`${prefixCls}-list__item-text`">{{ item.name }}</div>
<div :class="`${prefixCls}-list__item-enter`">
<g-icon icon="ant-design:enter-outlined" :size="20" />
</div>
</li>
</ul>
<AppSearchFooter />
</div>
</ClickOutSide>
</div>
</ClickOutSide>
</div>
</transition>
</Teleport>
</template>
<script lang="ts">
import { defineComponent, computed, unref, ref } from 'vue';
Expand All @@ -54,15 +64,20 @@
import AppSearchFooter from './AppSearchFooter.vue';
import { useI18n } from '/@/hooks/web/useI18n';
import { ClickOutSide } from '/@/components/ClickOutSide';
import { useAppInject } from '/@/hooks/web/useAppInject';
export default defineComponent({
name: 'AppSearchModal',
components: { SearchOutlined, ClickOutSide, AppSearchFooter },
emits: ['close'],
props: {
visible: Boolean,
},
setup(_, { emit }) {
const scrollWrap = ref<ElRef>(null);
const { prefixCls } = useDesign('app-search-modal');
const { t } = useI18n();
const [refs, setRefs] = useRefs();
const { getIsMobile } = useAppInject();
const {
handleSearch,
Expand All @@ -77,9 +92,19 @@
return !keyword || unref(searchResult).length === 0;
});
const getClass = computed(() => {
return [
prefixCls,
{
[`${prefixCls}--mobile`]: unref(getIsMobile),
},
];
});
return {
t,
prefixCls,
getClass,
handleSearch,
searchResult,
activeIndex,
Expand All @@ -98,12 +123,12 @@
<style lang="less" scoped>
@import (reference) '../../../../design/index.less';
@prefix-cls: ~'@{namespace}-app-search-modal';
@footer-prefix-cls: ~'@{namespace}-app-search-footer';
.@{prefix-cls} {
position: fixed;
top: 0;
left: 0;
z-index: 100;
z-index: 800;
display: flex;
width: 100%;
height: 100%;
Expand All @@ -113,6 +138,43 @@
justify-content: center;
// backdrop-filter: blur(2px);
&--mobile {
padding: 0;
> div {
width: 100%;
}
.@{prefix-cls}-input {
width: calc(100% - 38px);
}
.@{prefix-cls}-cancel {
display: inline-block;
}
.@{prefix-cls}-content {
width: 100%;
height: 100%;
border-radius: 0;
}
.@{footer-prefix-cls} {
display: none;
}
.@{prefix-cls}-list {
height: calc(100% - 80px);
max-height: unset;
&__item {
&-enter {
opacity: 0 !important;
}
}
}
}
&-content {
position: relative;
width: 532px;
Expand All @@ -124,10 +186,16 @@
flex-direction: column;
}
&-input__wrapper {
display: flex;
padding: 14px 14px 0 14px;
justify-content: space-between;
align-items: center;
}
&-input {
width: calc(100% - 28px);
width: 100%;
height: 56px;
margin: 14px 14px 0 14px;
font-size: 1.5em;
color: #1c1e21;
Expand All @@ -136,6 +204,12 @@
}
}
&-cancel {
display: none;
font-size: 1em;
color: #666;
}
&-not-data {
display: flex;
width: 100%;
Expand Down
2 changes: 1 addition & 1 deletion src/components/Menu/src/BasicMenu.vue
Original file line number Diff line number Diff line change
Expand Up @@ -151,7 +151,7 @@
if (props.mode !== MenuModeEnum.HORIZONTAL) {
setOpenKeys(path);
}
if (unref(getIsTopMenu)) {
if (props.isHorizontal && unref(getSplit)) {
const parentPath = await getCurrentParentPath(path);
menuState.selectedKeys = [parentPath];
} else {
Expand Down
12 changes: 6 additions & 6 deletions src/hooks/setting/useMenuSetting.ts
Original file line number Diff line number Diff line change
Expand Up @@ -50,11 +50,7 @@ const getShowTopMenu = computed(() => {
});

const getShowHeaderTrigger = computed(() => {
if (
unref(getMenuType) === MenuTypeEnum.TOP_MENU ||
!unref(getShowMenu) ||
!unref(getMenuHidden)
) {
if (unref(getMenuType) === MenuTypeEnum.TOP_MENU || !unref(getShowMenu) || unref(getMenuHidden)) {
return false;
}

Expand All @@ -79,7 +75,11 @@ const getMiniWidthNumber = computed(() => {
});

const getCalcContentWidth = computed(() => {
const width = unref(getIsTopMenu) || !unref(getShowMenu) ? 0 : unref(getRealWidth);
const width =
unref(getIsTopMenu) || !unref(getShowMenu) || (unref(getSplit) && unref(getMenuHidden))
? 0
: unref(getRealWidth);

return `calc(100% - ${unref(width)}px)`;
});

Expand Down
Loading

0 comments on commit c774a6d

Please sign in to comment.