初步构建起页面布局

This commit is contained in:
2026-01-23 17:55:26 +08:00
parent 2b0ee0c8b6
commit b6ad549737
37 changed files with 13405 additions and 5385 deletions

453
layouts/admin/defaults.uvue Normal file
View File

@@ -0,0 +1,453 @@
<!-- CRMEB Admin Defaults布局 - uni-app版本 -->
<template>
<view class="layout-container">
<!-- 侧边栏 -->
<AdminAside
:is-collapsed="isCollapsed"
:menu-list="menuList"
:active-menu="activeMenu"
@toggle-collapse="handleToggleCollapse"
@menu-click="handleMenuClick"
/>
<!-- 主内容区域 -->
<view class="main-container" :class="{ 'main-collapsed': isCollapsed }">
<!-- 顶部导航栏 -->
<AdminHeader
:is-collapsed="isCollapsed"
:current-page-title="currentPageTitle"
@toggle-collapse="handleToggleCollapse"
/>
<!-- 页面内容 -->
<view class="page-content">
<scroll-view
class="content-scroll"
scroll-y="true"
:style="{ height: contentHeight }"
>
<slot></slot>
</scroll-view>
</view>
<!-- 返回顶部按钮 -->
<view
class="back-top"
v-if="showBackTop"
@click="scrollToTop"
>
<text class="iconfont icon-top"></text>
</view>
</view>
<!-- 移动端遮罩 -->
<view
class="mobile-overlay"
v-if="showOverlay"
@click="closeSidebar"
></view>
</view>
</template>
<script>
import AdminAside from './aside.uvue'
import AdminHeader from './header.uvue'
import type { MenuItem } from './types.uts'
export default {
name: 'AdminDefaults',
components: {
AdminAside,
AdminHeader
},
props: {
currentPage: {
type: String,
required: true
}
},
data() {
return {
isCollapsed: false,
showOverlay: false,
showBackTop: false,
activeMenu: '',
openMenus: [] as string[],
menuList: [] as MenuItem[],
contentHeight: '100vh',
scrollTop: 0
}
},
computed: {
currentPageTitle() {
const findMenuTitle = (menus: MenuItem[]): string => {
for (const menu of menus) {
if (menu.id === this.activeMenu) {
return menu.title
}
if (menu.children) {
const subTitle = findMenuTitle(menu.children)
if (subTitle) return subTitle
}
}
return '管理后台'
}
return findMenuTitle(this.menuList)
}
},
onLoad() {
this.initLayout()
this.initMenuData()
this.updateActiveMenu()
},
onShow() {
this.updateActiveMenu()
},
methods: {
// 初始化布局
initLayout() {
// 获取侧边栏状态
const collapsed = uni.getStorageSync('admin_sidebar_collapsed')
this.isCollapsed = collapsed === true
// 获取展开的菜单
const openMenus = uni.getStorageSync('admin_open_menus')
if (openMenus) {
this.openMenus = openMenus
}
// 设置内容高度
this.setContentHeight()
},
// 初始化菜单数据
initMenuData() {
// 这里应该从配置或API获取菜单数据
// 暂时使用静态数据实际项目中应该从配置文件或API获取
this.menuList = [
{
id: 'dashboard',
title: '首页',
icon: 'icon-shujutongji',
path: '/pages/mall/admin/index'
},
{
id: 'user',
title: '用户管理',
icon: 'icon-yonghuguanli',
children: [
{
id: 'user-list',
title: '用户列表',
icon: 'icon-yonghuguanli',
path: '/pages/mall/admin/user-management'
},
{
id: 'user-detail',
title: '用户详情',
icon: 'icon-yonghuguanli',
path: '/pages/mall/admin/user-detail'
}
]
},
{
id: 'merchant',
title: '商家管理',
icon: 'icon-shangjiaguanli',
children: [
{
id: 'merchant-list',
title: '商家列表',
icon: 'icon-shangjiaguanli',
path: '/pages/mall/admin/merchant-management'
},
{
id: 'merchant-review',
title: '商家审核',
icon: 'icon-shenhe',
path: '/pages/mall/admin/merchant-review'
}
]
},
{
id: 'product',
title: '商品管理',
icon: 'icon-shangpinguanli',
children: [
{
id: 'product-list',
title: '商品列表',
icon: 'icon-shangpinguanli',
path: '/pages/mall/admin/product-management'
},
{
id: 'product-review',
title: '商品审核',
icon: 'icon-shenhe',
path: '/pages/mall/admin/product-review'
}
]
},
{
id: 'order',
title: '订单管理',
icon: 'icon-dingdanguanli',
path: '/pages/mall/admin/order-management'
},
{
id: 'finance',
title: '财务管理',
icon: 'icon-caiwuguanli',
path: '/pages/mall/admin/finance-management'
},
{
id: 'marketing',
title: '营销管理',
icon: 'icon-yingxiaoguanli',
children: [
{
id: 'coupon',
title: '优惠券',
icon: 'icon-youhuiquan',
path: '/pages/mall/admin/coupon-management'
},
{
id: 'marketing-main',
title: '营销活动',
icon: 'icon-yingxiaoguanli',
path: '/pages/mall/admin/marketing-management'
}
]
},
{
id: 'delivery',
title: '配送管理',
icon: 'icon-dingdanguanli',
path: '/pages/mall/admin/delivery-management'
},
{
id: 'subscription',
title: '订阅管理',
icon: 'icon-gongnengdaohang',
children: [
{
id: 'plan-management',
title: '方案管理',
icon: 'icon-gongnengdaohang',
path: '/pages/mall/admin/subscription/plan-management'
},
{
id: 'user-subscriptions',
title: '用户订阅',
icon: 'icon-gongnengdaohang',
path: '/pages/mall/admin/subscription/user-subscriptions'
}
]
},
{
id: 'review',
title: '审核管理',
icon: 'icon-shenhe',
children: [
{
id: 'product-review',
title: '商品审核',
icon: 'icon-shenhe',
path: '/pages/mall/admin/product-review'
},
{
id: 'merchant-review',
title: '商家审核',
icon: 'icon-shenhe',
path: '/pages/mall/admin/merchant-review'
},
{
id: 'refund-review',
title: '退款处理',
icon: 'icon-shenhe',
path: '/pages/mall/admin/refund-review'
}
]
},
{
id: 'complaints',
title: '投诉处理',
icon: 'icon-tousu',
path: '/pages/mall/admin/complaints'
},
{
id: 'notification',
title: '通知中心',
icon: 'icon-notification',
path: '/pages/mall/admin/notifications'
},
{
id: 'activity-log',
title: '活动日志',
icon: 'icon-rizhi',
path: '/pages/mall/admin/activity-log'
},
{
id: 'layout-test',
title: '布局测试',
icon: 'icon-kaifa',
path: '/pages/mall/admin/layout-test'
},
{
id: 'system',
title: '系统设置',
icon: 'icon-xitongshezhi',
path: '/pages/mall/admin/system-settings'
}
]
},
// 更新当前激活的菜单
updateActiveMenu() {
// 使用传入的currentPage prop来设置激活菜单
if (this.currentPage) {
this.activeMenu = this.currentPage
}
},
// 处理侧边栏切换
handleToggleCollapse() {
this.isCollapsed = !this.isCollapsed
uni.setStorageSync('admin_sidebar_collapsed', this.isCollapsed)
// 移动端处理
if (this.isMobile() && !this.isCollapsed) {
this.showOverlay = true
} else {
this.showOverlay = false
}
},
// 处理菜单点击
handleMenuClick(menu: MenuItem) {
if (menu.children && menu.children.length > 0) {
// 有子菜单,切换展开状态
const index = this.openMenus.indexOf(menu.id)
if (index > -1) {
this.openMenus.splice(index, 1)
} else {
this.openMenus.push(menu.id)
}
uni.setStorageSync('admin_open_menus', this.openMenus)
} else if (menu.path) {
// 叶子节点,跳转页面
this.activeMenu = menu.id
uni.navigateTo({
url: menu.path,
fail: () => {
// 如果navigateTo失败尝试switchTab
uni.switchTab({
url: menu.path
})
}
})
}
},
// 关闭侧边栏(移动端)
closeSidebar() {
if (this.isMobile()) {
this.isCollapsed = true
this.showOverlay = false
uni.setStorageSync('admin_sidebar_collapsed', true)
}
},
// 设置内容高度
setContentHeight() {
const systemInfo = uni.getSystemInfoSync()
// 减去顶部导航栏高度约88rpx和底部安全区域
this.contentHeight = `calc(${systemInfo.windowHeight}px - 88rpx)`
},
// 滚动到顶部
scrollToTop() {
this.scrollTop = 0
},
// 判断是否为移动端
isMobile(): boolean {
const systemInfo = uni.getSystemInfoSync()
return systemInfo.windowWidth < 768
}
}
}
</script>
<style lang="scss">
.layout-container {
display: flex;
height: 100vh;
background-color: #f0f2f5;
}
/* 主内容区域 */
.main-container {
flex: 1;
display: flex;
flex-direction: column;
transition: margin-left 0.3s ease;
background-color: #f0f2f5;
}
.main-collapsed {
margin-left: 80rpx;
}
/* 页面内容 */
.page-content {
flex: 1;
overflow: hidden;
}
.content-scroll {
height: 100%;
padding: 20rpx;
}
/* 返回顶部按钮 */
.back-top {
position: fixed;
right: 40rpx;
bottom: 40rpx;
width: 80rpx;
height: 80rpx;
background-color: #1890ff;
border-radius: 50%;
display: flex;
align-items: center;
justify-content: center;
color: #fff;
font-size: 32rpx;
box-shadow: 0 4rpx 12rpx rgba(24, 144, 255, 0.3);
z-index: 1000;
}
.back-top:active {
transform: scale(0.95);
}
/* 移动端遮罩 */
.mobile-overlay {
position: fixed;
top: 0;
left: 0;
right: 0;
bottom: 0;
background-color: rgba(0, 0, 0, 0.5);
z-index: 999;
}
/* 响应式设计 */
@media screen and (max-width: 768rpx) {
.main-collapsed {
margin-left: 0 !important;
}
}
</style>