消息移动适配

This commit is contained in:
2025-12-17 11:58:05 +08:00
parent e54456f434
commit 825a511b6f

View File

@@ -46,7 +46,7 @@
</el-form> </el-form>
<!-- 消息列表 --> <!-- 消息列表 -->
<div class="message-cards" v-loading="loading"> <div ref="messageContainerRef" class="message-cards" v-loading="loading">
<el-checkbox-group v-model="selectedMessages" class="message-group"> <el-checkbox-group v-model="selectedMessages" class="message-group">
<div <div
v-for="msg in messageList" v-for="msg in messageList"
@@ -115,10 +115,21 @@
v-if="messageList.length === 0 && !loading" v-if="messageList.length === 0 && !loading"
description="暂无消息" description="暂无消息"
/> />
<!-- 移动端加载更多提示 -->
<div v-if="isMobileDevice" class="mobile-load-more">
<div v-if="loadingMore" class="loading-tip">
<el-icon class="is-loading"><Loading /></el-icon>
<span>加载中...</span>
</div>
<div v-else-if="!hasMore && messageList.length > 0" class="no-more-tip">
没有更多了
</div>
</div>
</div> </div>
<!-- 分页组件 --> <!-- 分页组件 (移动端隐藏) -->
<div class="pagination-container"> <div v-if="!isMobileDevice" class="pagination-container">
<el-pagination <el-pagination
v-model:current-page="pageParam.pageNumber" v-model:current-page="pageParam.pageNumber"
v-model:page-size="pageParam.pageSize" v-model:page-size="pageParam.pageSize"
@@ -133,12 +144,13 @@
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
import { ref, onMounted } from 'vue'; import { ref, computed, onMounted, onUnmounted, nextTick, watch } from 'vue';
import { useRouter } from 'vue-router'; import { useRouter } from 'vue-router';
import { ElMessage } from 'element-plus'; import { ElMessage } from 'element-plus';
import { Refresh, Check, User, Clock } from '@element-plus/icons-vue'; import { Refresh, Check, User, Clock, Loading } from '@element-plus/icons-vue';
import { messageApi } from '@/apis/message'; import { messageApi } from '@/apis/message';
import type { MessageUserVO, PageParam } from '@/types'; import type { MessageUserVO, PageParam } from '@/types';
import { useDevice } from '@/utils/deviceUtils';
import { MessagePriorityBadge } from '@/components/message'; import { MessagePriorityBadge } from '@/components/message';
defineOptions({ defineOptions({
@@ -148,6 +160,11 @@ defineOptions({
const router = useRouter(); const router = useRouter();
const loading = ref(false); const loading = ref(false);
// 移动端相关
const { isMobileDevice } = useDevice();
const loadingMore = ref(false);
const messageContainerRef = ref<HTMLElement | null>(null);
const messageList = ref<MessageUserVO[]>([]); const messageList = ref<MessageUserVO[]>([]);
const selectedMessages = ref<string[]>([]); const selectedMessages = ref<string[]>([]);
const unreadCount = ref(0); const unreadCount = ref(0);
@@ -158,6 +175,7 @@ const pageParam = ref<PageParam>({
pageSize: 10 pageSize: 10
}); });
const total = ref(0); const total = ref(0);
const hasMore = computed(() => messageList.value.length < total.value);
// 筛选表单 // 筛选表单
const filterForm = ref<Partial<MessageUserVO>>({ const filterForm = ref<Partial<MessageUserVO>>({
@@ -261,6 +279,7 @@ async function loadUnreadCount() {
/** 搜索 */ /** 搜索 */
function handleSearch() { function handleSearch() {
pageParam.value.pageNumber = 1; pageParam.value.pageNumber = 1;
messageList.value = []; // 清空列表
loadMessages(); loadMessages();
} }
@@ -269,6 +288,7 @@ function handleReset() {
filterForm.value = { filterForm.value = {
isRead: undefined isRead: undefined
}; };
messageList.value = []; // 清空列表
handleSearch(); handleSearch();
} }
@@ -340,7 +360,78 @@ async function handleMarkAllRead() {
onMounted(() => { onMounted(() => {
loadMessages(); loadMessages();
loadUnreadCount(); loadUnreadCount();
// 移动端添加滚动监听
nextTick(() => {
if (isMobileDevice.value && messageContainerRef.value) {
setupInfiniteScroll();
}
}); });
});
onUnmounted(() => {
if (messageContainerRef.value) {
messageContainerRef.value.removeEventListener('scroll', handleScroll);
}
});
// 监听设备变化
watch(isMobileDevice, (isMobile) => {
if (isMobile) {
nextTick(() => {
if (messageContainerRef.value) {
setupInfiniteScroll();
}
});
} else {
if (messageContainerRef.value) {
messageContainerRef.value.removeEventListener('scroll', handleScroll);
}
}
});
// 设置无限滚动
function setupInfiniteScroll() {
if (!messageContainerRef.value) return;
messageContainerRef.value.addEventListener('scroll', handleScroll, { passive: true });
}
// 滚动加载更多
function handleScroll() {
if (!isMobileDevice.value || loading.value || loadingMore.value || !hasMore.value) return;
const container = messageContainerRef.value;
if (!container) return;
const { scrollTop, scrollHeight, clientHeight } = container;
const distanceFromBottom = scrollHeight - scrollTop - clientHeight;
if (distanceFromBottom <= 50) {
loadMoreMessages();
}
}
// 加载更多消息
async function loadMoreMessages() {
if (!hasMore.value || loadingMore.value) return;
loadingMore.value = true;
try {
const nextPage = pageParam.value.pageNumber + 1;
const result = await messageApi.getMyMessages(
{ ...pageParam.value, pageNumber: nextPage },
filterForm.value
);
if (result.success && result.dataList) {
messageList.value = [...messageList.value, ...result.dataList];
pageParam.value.pageNumber = nextPage;
total.value = result.pageParam?.totalElements || 0;
}
} catch (error) {
console.error('加载更多消息失败:', error);
} finally {
loadingMore.value = false;
}
}
</script> </script>
<style lang="scss" scoped> <style lang="scss" scoped>
@@ -505,6 +596,171 @@ onMounted(() => {
} }
} }
// 移动端加载更多提示
.mobile-load-more {
padding: 20px 0;
text-align: center;
.loading-tip {
display: flex;
align-items: center;
justify-content: center;
gap: 8px;
color: #c8232c;
font-size: 14px;
.is-loading {
animation: rotating 1s linear infinite;
}
}
.no-more-tip {
color: #9CA3AF;
font-size: 13px;
}
}
@keyframes rotating {
from { transform: rotate(0deg); }
to { transform: rotate(360deg); }
}
}
// 移动端样式适配
@media screen and (max-width: 768px) {
.my-message-list {
padding: 12px;
width: 100%;
.header {
flex-direction: column;
align-items: flex-start;
gap: 12px;
margin-bottom: 16px;
h2 {
font-size: 20px;
}
.header-actions {
width: 100%;
justify-content: flex-end;
.el-button {
padding: 8px 12px;
font-size: 13px;
}
}
}
.filter-form {
padding: 12px;
gap: 12px;
flex-direction: column;
align-items: stretch;
:deep(.el-form-item) {
width: 100%;
margin-right: 0;
.el-form-item__label {
width: 70px;
font-size: 13px;
}
.el-form-item__content {
flex: 1;
}
}
:deep(.el-select) {
width: 100% !important;
}
.filter-actions {
width: 100%;
justify-content: flex-end;
.el-button {
min-width: 70px;
}
}
}
.message-cards {
max-height: calc(100vh - 280px);
overflow-y: auto;
.message-group {
gap: 12px;
}
.message-card {
padding: 12px;
.card-header {
flex-wrap: wrap;
gap: 8px;
.card-title-area {
flex: 1 1 calc(100% - 40px);
min-width: 0;
.card-title {
font-size: 14px;
}
}
.card-actions {
width: 100%;
justify-content: flex-end;
margin-top: 4px;
.el-button {
font-size: 12px;
}
}
}
.card-body {
.message-meta {
gap: 8px;
font-size: 12px;
.sender-info {
max-width: 150px;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
}
.message-preview {
font-size: 13px;
-webkit-line-clamp: 2;
line-clamp: 2;
display: -webkit-box;
-webkit-box-orient: vertical;
overflow: hidden;
}
}
}
}
.pagination-container {
padding: 12px 0;
:deep(.el-pagination) {
flex-wrap: wrap;
justify-content: center;
.el-pagination__total,
.el-pagination__sizes,
.el-pagination__jump {
display: none;
}
}
}
}
} }
</style> </style>