Commit 0fd0cb01 by Sweet Zhang

分页对接,菜单可折叠

parent 79fddc42
......@@ -6,7 +6,12 @@
<!-- 主应用布局 -->
<div v-else class="flex flex-1 h-screen">
<!-- 侧边导航 -->
<Sidebar :current-page="currentPage" @logout="handleLogout" />
<Sidebar
:current-page="currentPage"
:collapsed="sidebarCollapsed"
@logout="handleLogout"
@toggle-collapse="toggleSidebar"
/>
<!-- 移动端菜单按钮 -->
<button
......@@ -25,7 +30,10 @@
/>
<!-- 主内容区域 -->
<div class="flex-1 flex flex-col">
<div
class="flex-1 flex flex-col transition-all duration-300"
:class="sidebarCollapsed ? 'ml-16' : 'ml-64'"
>
<main class="flex-1 overflow-y-auto bg-gray-50 p-4 md:p-6">
<header class="mb-6">
<h2 class="text-2xl font-bold text-gray-800">
......@@ -47,6 +55,7 @@ import { useRoute, useRouter } from 'vue-router'
import LoginPage from './views/LoginPage.vue'
import Sidebar from './views/Sidebar.vue'
import MobileSidebar from './views/MobileSidebar.vue'
import { pageTitles } from '@/utils/menuConfig'
const route = useRoute()
const router = useRouter()
......@@ -56,6 +65,7 @@ const isLoginPage = ref(true)
const isAuthenticated = ref(false)
const currentPage = ref('compose')
const showMobileMenu = ref(false)
const sidebarCollapsed = ref(false) // 新增:侧边栏折叠状态
// 监听路由变化,更新当前页面状态
watch(
......@@ -67,13 +77,9 @@ watch(
},
)
// 页面标题映射(保持不变)
const pageTitles = {
compose: '写邮件',
contacts: '联系人管理',
senders: '发件人管理',
variables: '变量管理',
emails: '邮件记录',
// 切换侧边栏折叠状态
const toggleSidebar = () => {
sidebarCollapsed.value = !sidebarCollapsed.value
}
// 方法(移除页面切换相关方法)
......
// 菜单项接口定义
export interface MenuItem {
name: string
path: string
icon: string
title: string
}
// 菜单配置
export const menuConfig: MenuItem[] = [
{
name: 'compose',
path: '/compose',
icon: 'fas fa-pen',
title: '写邮件',
},
{
name: 'contacts',
path: '/contacts',
icon: 'fas fa-address-book',
title: '联系人管理',
},
{
name: 'senders',
path: '/senders',
icon: 'fas fa-user-circle',
title: '发件人管理',
},
{
name: 'variables',
path: '/variables',
icon: 'fas fa-file-excel',
title: '变量管理',
},
{
name: 'emails',
path: '/emails',
icon: 'fas fa-history',
title: '邮件记录',
},
]
// 页面标题映射
export const pageTitles: Record<string, string> = {
compose: '写邮件',
contacts: '联系人管理',
senders: '发件人管理',
variables: '变量管理',
emails: '邮件记录',
}
......@@ -196,7 +196,7 @@
:records="importRecords"
@update-record="updateImportRecord"
@delete-record="deleteImportRecord"
@close="((showImportRecordManager = false), getImportedContacts())"
@close="showImportRecordManager = false"
/>
<!-- 导入数据弹窗 -->
......@@ -397,7 +397,7 @@ const updateImportRecord = (updatedRecord: ImportRecord) => {
type: 'success',
})
// 更新成功之后,刷新导入记录列表
getImportedContacts(emailForm.value.sessionId || '')
getImportedContacts(emailForm.value.sessionId || '', 'update')
} else {
ElMessage({
message: '导入记录更新失败',
......@@ -468,7 +468,7 @@ const sendEmail = () => {
}
// 通过sessionId获取导入的联系人
const getImportedContacts = (sessionId?: string) => {
const getImportedContacts = (sessionId?: string, type?: string) => {
const params = {
sessionId: sessionId || emailForm.value.sessionId || '',
source: importSource.value,
......@@ -477,9 +477,14 @@ const getImportedContacts = (sessionId?: string) => {
if (res.code === 200) {
console.log('导入的联系人:', res.data)
importRecords.value = res.data.records || []
// 更新页面展示的抄送人和收件人
// emailForm.value.receiveEmail = res.data?.receiveEmails || ''
// emailForm.value.ccEmails = res.data?.ccEmails || ''
// 从导入记录中提取收件人和抄送人
if (type == 'update') {
debugger
emailForm.value.receiveEmail = importRecords.value
.map((item) => item.receiveEmail)
.join(',')
emailForm.value.ccEmails = importRecords.value.map((item) => item.ccEmail).join(',')
}
}
})
}
......
......@@ -9,34 +9,14 @@
</div>
<nav>
<ul>
<li class="mb-2">
<li v-for="menu in menuItems" :key="menu.name" class="mb-2">
<router-link
to="/compose"
:to="menu.path"
class="w-full text-left px-4 py-2 rounded hover:bg-blue-500 transition-colors flex items-center block"
:class="{ 'bg-blue-500': currentPage === 'compose' }"
:class="{ 'bg-blue-500': currentPage === menu.name }"
@click="$emit('close-menu')"
>
<i class="fas fa-pen mr-2"></i>写邮件
</router-link>
</li>
<li class="mb-2">
<router-link
to="/variables"
class="w-full text-left px-4 py-2 rounded hover:bg-blue-500 transition-colors flex items-center block"
:class="{ 'bg-blue-500': currentPage === 'variables' }"
@click="$emit('close-menu')"
>
<i class="fas fa-file-excel mr-2"></i>变量管理
</router-link>
</li>
<li class="mb-2">
<router-link
to="/emails"
class="w-full text-left px-4 py-2 rounded hover:bg-blue-500 transition-colors flex items-center block"
:class="{ 'bg-blue-500': currentPage === 'emails' }"
@click="$emit('close-menu')"
>
<i class="fas fa-history mr-2"></i>邮件记录
<i :class="menu.icon" class="mr-2"></i>{{ menu.title }}
</router-link>
</li>
</ul>
......@@ -53,16 +33,22 @@
</div>
</template>
<script setup lang="ts">
import { ref, watch } from 'vue'
import { ref, watch, computed } from 'vue'
import { useRouter } from 'vue-router'
import { menuConfig } from '@/utils/menuConfig'
const router = useRouter()
const currentPage = ref(router.currentRoute.value.name as string)
// 使用统一的菜单配置
const menuItems = computed(() => menuConfig)
watch(
() => router.currentRoute.value.name,
(name) => {
currentPage.value = name as string
if (name) {
currentPage.value = name as string
}
},
)
</script>
<template>
<aside
class="bg-sky-700 text-white w-64 flex-shrink-0 hidden md:block transition-all duration-300 ease-in-out"
class="bg-sky-700 text-white flex-shrink-0 hidden md:block transition-all duration-300 ease-in-out fixed h-full z-40"
:class="collapsed ? 'w-16' : 'w-64'"
>
<div class="p-4 border-b border-blue-500">
<h1 class="text-xl font-bold">邮件系统</h1>
<!-- 顶部区域 -->
<div class="p-4 border-b border-blue-500 flex items-center justify-between">
<h1
class="text-xl font-bold transition-all duration-300"
:class="collapsed ? 'opacity-0 w-0' : 'opacity-100'"
>
邮件系统
</h1>
<button
@click="$emit('toggle-collapse')"
class="p-1 rounded hover:bg-blue-500 transition-colors flex items-center justify-center"
:title="collapsed ? '展开菜单' : '折叠菜单'"
>
<i class="fas" :class="collapsed ? 'fa-chevron-right' : 'fa-chevron-left'"></i>
</button>
</div>
<!-- 导航菜单 -->
<nav class="p-4">
<ul>
<li class="mb-2">
<router-link
to="/compose"
class="w-full text-left px-4 py-2 rounded hover:bg-blue-500 transition-colors flex items-center block"
:class="{ 'bg-blue-500': currentPage === 'compose' }"
>
<i class="fas fa-pen mr-2"></i>写邮件
</router-link>
</li>
<li class="mb-2">
<router-link
to="/contacts"
class="w-full text-left px-4 py-2 rounded hover:bg-blue-500 transition-colors flex items-center block"
:class="{ 'bg-blue-500': currentPage === 'contacts' }"
>
<i class="fas fa-address-book mr-2"></i>联系人管理
</router-link>
</li>
<li class="mb-2">
<li v-for="menu in menuItems" :key="menu.name" class="mb-2">
<router-link
to="/senders"
class="w-full text-left px-4 py-2 rounded hover:bg-blue-500 transition-colors flex items-center block"
:class="{ 'bg-blue-500': currentPage === 'senders' }"
:to="menu.path"
class="w-full text-left px-4 py-2 rounded hover:bg-blue-500 transition-colors flex items-center"
:class="{
'bg-blue-500': currentPage === menu.name,
'justify-center': collapsed,
'justify-start': !collapsed,
}"
:title="collapsed ? menu.title : ''"
>
<i class="fas fa-user-circle mr-2"></i>发件人管理
</router-link>
</li>
<li class="mb-2">
<router-link
to="/variables"
class="w-full text-left px-4 py-2 rounded hover:bg-blue-500 transition-colors flex items-center block"
:class="{ 'bg-blue-500': currentPage === 'variables' }"
>
<i class="fas fa-file-excel mr-2"></i>变量管理
</router-link>
</li>
<li class="mb-2">
<router-link
to="/emails"
class="w-full text-left px-4 py-2 rounded hover:bg-blue-500 transition-colors flex items-center block"
:class="{ 'bg-blue-500': currentPage === 'emails' }"
>
<i class="fas fa-history mr-2"></i>邮件记录
<i :class="[menu.icon, collapsed ? '' : 'mr-2']" class="flex-shrink-0"></i>
<span
class="transition-all duration-300"
:class="collapsed ? 'opacity-0 w-0 ml-0' : 'opacity-100 ml-2'"
>
{{ menu.title }}
</span>
</router-link>
</li>
</ul>
</nav>
<!-- 底部退出按钮 -->
<div class="absolute bottom-4 left-0 right-0 px-4">
<button
@click="$emit('logout')"
class="text-left px-4 py-2 rounded hover:bg-blue-500 transition-colors flex items-center text-sm"
class="w-full text-left px-4 py-2 rounded hover:bg-blue-500 transition-colors flex items-center justify-center text-sm"
:class="collapsed ? 'justify-center' : 'justify-start'"
:title="collapsed ? '退出登录' : ''"
>
<i class="fas fa-sign-out-alt mr-2"></i>退出登录
<i class="fas fa-sign-out-alt flex-shrink-0" :class="collapsed ? '' : 'mr-2'"></i>
<span
class="transition-all duration-300"
:class="collapsed ? 'opacity-0 w-0' : 'opacity-100'"
>
退出登录
</span>
</button>
</div>
</aside>
</template>
<script setup lang="ts">
import { defineProps, defineEmits } from 'vue'
import { defineProps, defineEmits, computed } from 'vue'
import { menuConfig } from '@/utils/menuConfig'
const props = defineProps({
currentPage: {
type: String,
required: true,
},
collapsed: {
type: Boolean,
default: false,
},
})
const emits = defineEmits(['logout'])
const emits = defineEmits(['logout', 'toggle-collapse'])
// 使用统一的菜单配置
const menuItems = computed(() => menuConfig)
</script>
<style scoped>
/* 确保折叠时图标居中 */
.router-link-active {
@apply bg-blue-500;
}
/* 优化折叠状态下的样式 */
aside {
box-shadow: 2px 0 10px rgba(0, 0, 0, 0.1);
}
/* 防止文字在折叠时显示 */
span {
white-space: nowrap;
overflow: hidden;
}
/* 增加菜单项的可点击区域 */
li a {
min-height: 44px; /* 确保触摸友好的最小高度 */
cursor: pointer;
}
/* 优化折叠状态下的交互体验 */
li a:hover {
background-color: rgba(59, 130, 246, 0.8);
}
/* 确保图标和文字垂直对齐 */
li a {
align-items: center;
}
/* 优化图标和文字的间距 */
i {
width: 1.25rem; /* 固定图标宽度 */
text-align: center;
}
</style>
......@@ -189,6 +189,16 @@
<i class="fas fa-variable text-4xl mb-3 opacity-30"></i>
<p>暂无变量,请添加变量</p>
</div>
<!-- 分页组件 -->
<Pagination
:total="total"
:current="currentPage"
:page-size="pageSize"
@change="handlePageChange"
@update:current="handleCurrentUpdate"
@update:page-size="handlePageSizeUpdate"
/>
</div>
<!-- 变量模板弹窗 -->
......@@ -292,6 +302,31 @@ import type { Variable, VariableTemplate } from '../types'
import { variableApi, variableGroupApi } from '@/api/api'
import { ElMessage } from 'element-plus'
// 引入分页组件
import Pagination from '@/components/Pagination.vue'
// 初始数据
const total = ref(0)
const currentPage = ref(1)
const pageSize = ref(10)
// 处理分页变化
const handlePageChange = (page: number, size: number) => {
console.log('分页变化:', page, size)
fetchVariables()
// 这里可以发起API请求获取新数据
}
const handleCurrentUpdate = (page: number) => {
currentPage.value = page
}
const handlePageSizeUpdate = (size: number) => {
pageSize.value = size
currentPage.value = 1 // 重置到第一页
}
// 引入弹窗组件
import CommonModal from '@/components/CommonModal.vue'
// 弹窗提示信息对象
......@@ -474,13 +509,14 @@ const deleteVariable = (id: string, type?: string) => {
// 查询变量列表
const fetchVariables = () => {
const params = {
pageNo: 1,
pageSize: 10,
pageNo: currentPage.value,
pageSize: pageSize.value,
}
variableApi
.getEmailVariableList(params)
.then((res) => {
variables.value = res.data.records || []
total.value = res.data.total || 0
})
.catch((error) => {
console.error('查询变量列表失败:', error)
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment