Files
im-uniapp/pages/workbench/feedback/feedback.vue
2025-08-20 13:44:05 +08:00

375 lines
8.3 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<template>
<view class="message-list-page">
<!-- 顶部导航栏 -->
<view class="navbar">
<view class="icon-btn" @click="toggleFilter">
<uni-icons type="gear" size="22"></uni-icons>
</view>
<uni-easyinput v-model="queryParams.title" placeholder="搜索反馈..." @confirm="handleSearch"
@clear="handleClearSearch"></uni-easyinput>
<view class="icon-btn" @click="navigateToAdd">
<uni-icons type="plus" size="22"></uni-icons>
</view>
</view>
<!-- 搜索和筛选区域 -->
<view class="filter-row" v-if="showFilter">
<uni-datetime-picker type="daterange" v-model="dateRange" startDate="2020-01-01" endDate="2030-12-31"
@change="handleDateChange" placeholder="选择时间范围"></uni-datetime-picker>
<oa-project-select v-model="queryParams.projectId" @change="handleSearch"></oa-project-select>
</view>
<!-- 消息列表使用scroll-view实现下拉加载 -->
<scroll-view scroll-y @scrolltolower="loadMore" :style="{ height: scrollHeight + 'px' }" class="message-scroll">
<view class="message-list">
<view v-for="(msg, index) in messageList" :key="msg.feedbackId" class="message-item"
:class="{ 'unread': msg.state === 0 }" @click="navigateToDetail(msg)" @longpress="handleDel(msg)"
>
<!-- 消息标题 -->
<view class="message-title">
<view class="state-dot" v-if="msg.state === 0"></view>
<text>{{ msg.title }}</text>
</view>
<!-- 消息信息 -->
<view class="message-info">
<text class="message-status">{{ msg.state === 0 ? '未读' : '已读' }}</text>
<text class="project-name">
{{ msg.projectName ? truncateText(msg.projectName, 15) : '无项目' }}
</text>
<text class="create-time">{{ formatTime(msg.createTime) }}</text>
</view>
</view>
<!-- 空状态 -->
<uni-empty v-if="messageList.length === 0 && !loading" text="暂无消息"></uni-empty>
</view>
<!-- 加载更多组件 -->
<uni-load-more :status="loadMoreStatus" class="load-more"></uni-load-more>
</scroll-view>
</view>
</template>
<script>
import {
delFeedback,
listFeedback
} from "@/api/oa/feedback";
export default {
data() {
return {
// 消息列表数据不再需要filteredMessageList
messageList: [],
// 分页查询参数
queryParams: {
pageSize: 10,
pageNum: 1,
title: '',
projectId: '',
startTime: '',
endTime: ''
},
total: 0, // 总条数
loading: false, // 加载状态
showFilter: false, // 筛选框显示状态
dateRange: [], // 日期范围
loadMoreStatus: 'more', // 加载更多状态more/noMore/loading
scrollHeight: 0 // 滚动区域高度
};
},
onShow() {
// 重置分页数据并重新加载
this.resetPageData();
this.calculateScrollHeight();
},
methods: {
// 计算滚动区域高度
calculateScrollHeight() {
const systemInfo = uni.getSystemInfoSync();
const navbarHeight = 44; // 导航栏高度
const searchFilterHeight = 0; // 搜索筛选区域高度
this.scrollHeight = systemInfo.windowHeight - navbarHeight - searchFilterHeight;
},
// 重置分页数据
resetPageData() {
this.queryParams.pageNum = 1;
this.messageList = [];
this.loadMoreStatus = 'more';
this.getList();
},
// 获取消息列表
getList() {
// 如果正在加载或没有更多数据,直接返回
if (this.loading || this.loadMoreStatus !== 'more') return;
this.loading = true;
this.loadMoreStatus = 'loading'; // 显示加载中状态
listFeedback(this.queryParams)
.then(res => {
this.total = res.total || 0;
const newList = res.rows || [];
// 第一页直接赋值,后续页追加
if (this.queryParams.pageNum === 1) {
this.messageList = newList;
} else {
this.messageList = [...this.messageList, ...newList];
}
// 判断是否还有更多数据
if (this.messageList.length >= this.total) {
this.loadMoreStatus = 'noMore';
} else {
this.loadMoreStatus = 'more';
}
})
.catch(err => {
uni.showToast({
title: err.message || '获取消息失败',
icon: 'none'
});
this.loadMoreStatus = 'more'; // 加载失败时允许重试
})
.finally(() => {
this.loading = false;
});
},
// 加载更多
loadMore() {
if (this.loadMoreStatus === 'more' && !this.loading) {
this.queryParams.pageNum++;
this.getList();
}
},
// 搜索处理
handleSearch() {
// 搜索时重置分页
this.resetPageData();
},
// 处理删除
handleDel(row) {
uni.showModal({
title: '提示',
content: '确定要删除这条消息吗?',
success: (res) => {
if (res.confirm) {
delFeedback(row.feedbackId)
.then(() => {
uni.showToast({
title: '删除成功',
icon: 'success'
});
// 删除后重新加载列表
this.resetPageData();
})
.catch(err => {
uni.showToast({
title: err.message || '删除失败',
icon: 'none'
});
});
}
}
});
},
// 切换筛选
toggleFilter() {
this.showFilter = !this.showFilter;
},
// 处理日期范围变化
handleDateChange(e) {
if (e.length === 2) {
this.queryParams.startTime = e[0] + ' 00:00:00';
this.queryParams.endTime = e[1] + " 00:00:00";
this.resetPageData(); // 筛选后重置分页
}
},
// 清除搜索
handleClearSearch() {
this.queryParams.title = '';
this.resetPageData();
},
// 格式化时间
formatTime(time) {
if (!time) return '';
const date = new Date(time);
return `${date.getMonth() + 1}-${date.getDate()} ${date.getHours()}:${date.getMinutes()}`;
},
// 截断文本
truncateText(text, length = 15) {
if (!text) return '';
if (text.length <= length) return text;
return text.substring(0, length) + '...';
},
// 跳转到详情页
navigateToDetail(msg) {
uni.navigateTo({
url: `/pages/workbench/feedback/detail?feedbackId=${msg.feedbackId}`
});
},
// 跳转到新增页
navigateToAdd() {
uni.navigateTo({
url: '/pages/workbench/feedback/create'
});
}
}
};
</script>
<style scoped>
.message-list-page {
background-color: #f5f5f5;
min-height: 100vh;
}
.navbar {
display: flex;
justify-content: space-between;
align-items: center;
height: 44px;
width: 100vw;
box-sizing: border-box;
padding: 0 15px;
color: #fff;
}
.title {
font-size: 18px;
font-weight: bold;
}
.add-btn {
background-color: transparent;
border: none;
color: #fff;
padding: 5px 10px;
}
.search-filter {
padding: 10px 15px;
background-color: #fff;
position: relative;
/* 用于筛选按钮定位 */
}
.filter-row {
display: flex;
gap: 10px;
margin-top: 10px;
flex-wrap: wrap;
}
.filter-btn {
position: absolute;
right: 20px;
top: 15px;
background-color: transparent;
border: none;
display: flex;
align-items: center;
gap: 5px;
color: #666;
}
/* 滚动区域样式 */
.message-scroll {
width: 100%;
overflow: hidden;
}
.message-list {
padding: 10px 15px;
}
.message-item {
background-color: #fff;
border-radius: 8px;
padding: 15px;
margin-bottom: 10px;
display: flex;
flex-direction: column;
position: relative;
}
.message-item.unread {
border-left: 3px solid #fa5555;
}
.message-title {
display: flex;
align-items: center;
margin-bottom: 10px;
font-weight: 500;
font-size: 16px;
}
.state-dot {
width: 8px;
height: 8px;
border-radius: 50%;
background-color: #fa5555;
margin-right: 8px;
}
.message-info {
display: flex;
justify-content: space-between;
align-items: center;
color: #999;
font-size: 14px;
}
.message-status {
color: #fa5555;
}
.project-name {
flex: 1;
text-align: center;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
.create-time {
text-align: right;
}
.delete-btn {
position: absolute;
right: 10px;
top: 10px;
background-color: transparent;
border: none;
padding: 5px;
}
/* 加载更多样式 */
.load-more {
padding: 20rpx 0;
text-align: center;
}
.icon-btn {
padding: 10rpx;
margin: 10rpx;
box-sizing: border-box;
}
</style>