|
|
|
@ -24,11 +24,13 @@
|
|
|
|
</view>
|
|
|
|
</view>
|
|
|
|
|
|
|
|
|
|
|
|
<scroll-view scroll-y class="content-scroll" :scroll-top="scrollTop" scroll-with-animation @scroll="onScroll">
|
|
|
|
<scroll-view scroll-y class="content-scroll" :scroll-top="scrollTop" scroll-with-animation @scroll="onScroll">
|
|
|
|
<view class="content-inner">
|
|
|
|
<view class="content-inner" :class="{ 'safe-bottom': safeBottom }">
|
|
|
|
<view v-if="filteredModules.length === 0" class="empty-state">
|
|
|
|
<AppEmptyState
|
|
|
|
<text class="empty-title">暂无可用菜单</text>
|
|
|
|
v-if="filteredModules.length === 0"
|
|
|
|
<text class="empty-desc">当前账号未返回 {{ title }} 相关权限菜单</text>
|
|
|
|
:icon="emptyStateIcon"
|
|
|
|
</view>
|
|
|
|
:title="emptyStateTitle"
|
|
|
|
|
|
|
|
:desc="emptyStateDesc"
|
|
|
|
|
|
|
|
/>
|
|
|
|
|
|
|
|
|
|
|
|
<view v-for="(module, moduleIndex) in filteredModules" :key="module.id || `${pagePath}-${moduleIndex}`" class="module-section">
|
|
|
|
<view v-for="(module, moduleIndex) in filteredModules" :key="module.id || `${pagePath}-${moduleIndex}`" class="module-section">
|
|
|
|
<view class="module-header">
|
|
|
|
<view class="module-header">
|
|
|
|
@ -85,6 +87,7 @@
|
|
|
|
|
|
|
|
|
|
|
|
<script setup>
|
|
|
|
<script setup>
|
|
|
|
import { computed, ref } from 'vue'
|
|
|
|
import { computed, ref } from 'vue'
|
|
|
|
|
|
|
|
import AppEmptyState from '@/components/common/AppEmptyState.vue'
|
|
|
|
import useUserStore from '@/store/modules/user'
|
|
|
|
import useUserStore from '@/store/modules/user'
|
|
|
|
import { buildPageModules, findTabMenuByPage, getMenuSymbol, getModuleColor, resolveMenuUrl } from '@/utils/permissionMenu'
|
|
|
|
import { buildPageModules, findTabMenuByPage, getMenuSymbol, getModuleColor, resolveMenuUrl } from '@/utils/permissionMenu'
|
|
|
|
|
|
|
|
|
|
|
|
@ -108,6 +111,10 @@ const props = defineProps({
|
|
|
|
showGoTop: {
|
|
|
|
showGoTop: {
|
|
|
|
type: Boolean,
|
|
|
|
type: Boolean,
|
|
|
|
default: false
|
|
|
|
default: false
|
|
|
|
|
|
|
|
},
|
|
|
|
|
|
|
|
safeBottom: {
|
|
|
|
|
|
|
|
type: Boolean,
|
|
|
|
|
|
|
|
default: false
|
|
|
|
}
|
|
|
|
}
|
|
|
|
})
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
|
|
@ -144,6 +151,26 @@ const filteredModules = computed(() => {
|
|
|
|
.filter((module) => module.groups.length > 0 || String(module.name || '').toLowerCase().includes(keyword))
|
|
|
|
.filter((module) => module.groups.length > 0 || String(module.name || '').toLowerCase().includes(keyword))
|
|
|
|
})
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
const hasMenuPermission = computed(() => modules.value.length > 0)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
const isSearchEmpty = computed(() => {
|
|
|
|
|
|
|
|
return Boolean(menuSearchKeyword.value.trim()) && hasMenuPermission.value && filteredModules.value.length === 0
|
|
|
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
const emptyStateTitle = computed(() => {
|
|
|
|
|
|
|
|
return isSearchEmpty.value ? '未找到匹配菜单' : '请先配置菜单权限'
|
|
|
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
const emptyStateDesc = computed(() => {
|
|
|
|
|
|
|
|
return isSearchEmpty.value
|
|
|
|
|
|
|
|
? `未搜索到与“${menuSearchKeyword.value.trim()}”相关的菜单项,请调整关键词后重试`
|
|
|
|
|
|
|
|
: `当前账号还未配置${props.title}相关菜单权限,请联系管理员完成配置`
|
|
|
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
const emptyStateIcon = computed(() => {
|
|
|
|
|
|
|
|
return isSearchEmpty.value ? 'search' : 'locked-filled'
|
|
|
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
|
|
function clearMenuSearch() {
|
|
|
|
function clearMenuSearch() {
|
|
|
|
menuSearchKeyword.value = ''
|
|
|
|
menuSearchKeyword.value = ''
|
|
|
|
}
|
|
|
|
}
|
|
|
|
@ -200,13 +227,13 @@ function handleClick(menu) {
|
|
|
|
icon: 'none'
|
|
|
|
icon: 'none'
|
|
|
|
})
|
|
|
|
})
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
</script>
|
|
|
|
</script>
|
|
|
|
|
|
|
|
|
|
|
|
<style lang="scss" scoped>
|
|
|
|
<style lang="scss" scoped>
|
|
|
|
.page-container {
|
|
|
|
.page-container {
|
|
|
|
min-height: 100vh;
|
|
|
|
display: flex;
|
|
|
|
|
|
|
|
flex-direction: column;
|
|
|
|
|
|
|
|
height: 100%;
|
|
|
|
background-color: #f0f2f5;
|
|
|
|
background-color: #f0f2f5;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
@ -277,12 +304,15 @@ function handleClick(menu) {
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.content-scroll {
|
|
|
|
.content-scroll {
|
|
|
|
height: calc(100vh - 240rpx);
|
|
|
|
flex: 1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.content-inner {
|
|
|
|
.content-inner {
|
|
|
|
padding: 24rpx;
|
|
|
|
padding: 24rpx;
|
|
|
|
padding-bottom: 160rpx;
|
|
|
|
|
|
|
|
|
|
|
|
&.safe-bottom {
|
|
|
|
|
|
|
|
padding-bottom: calc(24rpx + 120rpx + env(safe-area-inset-bottom));
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.module-section {
|
|
|
|
.module-section {
|
|
|
|
@ -393,28 +423,6 @@ function handleClick(menu) {
|
|
|
|
margin: 24rpx 0 0;
|
|
|
|
margin: 24rpx 0 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.empty-state {
|
|
|
|
|
|
|
|
background: #ffffff;
|
|
|
|
|
|
|
|
border-radius: 28rpx;
|
|
|
|
|
|
|
|
padding: 80rpx 32rpx;
|
|
|
|
|
|
|
|
text-align: center;
|
|
|
|
|
|
|
|
box-shadow: 0 10rpx 30rpx rgba(26, 58, 92, 0.06);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
.empty-title {
|
|
|
|
|
|
|
|
display: block;
|
|
|
|
|
|
|
|
font-size: 34rpx;
|
|
|
|
|
|
|
|
font-weight: 600;
|
|
|
|
|
|
|
|
color: #1a3a5c;
|
|
|
|
|
|
|
|
margin-bottom: 16rpx;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
.empty-desc {
|
|
|
|
|
|
|
|
display: block;
|
|
|
|
|
|
|
|
font-size: 28rpx;
|
|
|
|
|
|
|
|
color: #7a8795;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
.go-top-btn {
|
|
|
|
.go-top-btn {
|
|
|
|
position: fixed;
|
|
|
|
position: fixed;
|
|
|
|
bottom: 140rpx;
|
|
|
|
bottom: 140rpx;
|
|
|
|
@ -427,7 +435,7 @@ function handleClick(menu) {
|
|
|
|
align-items: center;
|
|
|
|
align-items: center;
|
|
|
|
justify-content: center;
|
|
|
|
justify-content: center;
|
|
|
|
box-shadow: 0 8rpx 24rpx rgba(26, 58, 92, 0.3);
|
|
|
|
box-shadow: 0 8rpx 24rpx rgba(26, 58, 92, 0.3);
|
|
|
|
z-index: 10;
|
|
|
|
z-index: 50;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.go-top-icon {
|
|
|
|
.go-top-icon {
|
|
|
|
@ -435,5 +443,4 @@ function handleClick(menu) {
|
|
|
|
color: #ffffff;
|
|
|
|
color: #ffffff;
|
|
|
|
font-weight: bold;
|
|
|
|
font-weight: bold;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
</style>
|
|
|
|
</style>
|
|
|
|
|
|
|
|
|