Files
property-resident-side/property-uniapp-project/pageSubPack/service-list/complaintsSuggestionsIndex.vue
2026-08-20 15:41:27 +08:00

341 lines
6.4 KiB
Vue

<template>
<view class="contentStyle">
<!-- 顶部分段控制器 -->
<view class="tab-wrap">
<view class="tab-item" :class="{ active: currentTab === index }" v-for="(tab, index) in tabs"
:key="index" @click="onTabClick({ currentIndex: index })">
<text class="tab-text">{{ tab }}</text>
</view>
</view>
<!-- 列表区域 -->
<view class="page">
<view class="page-container">
<view v-if="dataList.length === 0" class="empty-state">
<uni-icons type="info" size="30" color="#ccc"></uni-icons>
<text class="empty-text">暂无数据</text>
</view>
<!-- 投诉卡片 -->
<view class="card-wrapper" v-for="(item, index) in dataList" :key="index">
<view class="card-header">
<text class="card-title">{{ item.title }}</text>
<text class="card-tag"
:class="item.status === 'pending' ? 'pending' : 'completed'">
{{ item.status === 'pending' ? '待处理' : '已完成' }}
</text>
</view>
<view class="card-body">
<text class="card-desc">{{ item.desc }}</text>
<view class="img-scroll-container">
<view v-for="(img, imgIndex) in item.imgList" :key="imgIndex" class="img-item">
<image :src="img" mode="aspectFill" class="card-img"></image>
</view>
</view>
<view class="card-footer">
<text class="card-time">{{ item.time }}</text>
<text class="card-detail" @click="turnToDetail(item)">投诉详情</text>
</view>
</view>
</view>
</view>
</view>
<!-- 底部按钮 -->
<view class="bottom-btn-wrap">
<button class="next-btn" @click="addComplaintsSuggestions">投诉建议</button>
</view>
</view>
</template>
<script setup>
import { ref, onMounted } from 'vue'
import {onLoad, onShow, onPullDownRefresh} from '@dcloudio/uni-app'
import {getComplainList} from '../api/apiSub.js'
// 分段器
const tabs = ref(["待处理", "已完成"])
const currentTab = ref(0)
const dataList = ref([])
// 模拟数据
const pendingList = ref([])
const processingList = ref([])
const completedList = ref([])
// 状态映射
const statusMap = {
"0":'pending',
// '1':'processing',
'1':'completed'
}
// 接口数据映射为模板所需格式
const mapItem = (item) => {
// 图片:单 URL 转数组
let imgList = []
if (item.problemImageUrl) {
imgList = [item.problemImageUrl]
}
return {
id: item.id,
title: item.typeName,
status: statusMap[item.status] || 'pending',
desc: item.problemDes || '',
time: item.createTime || '',
imgList
}
}
// 切换tab
const onTabClick = (e) => {
currentTab.value = e.currentIndex
getComplainListData()
}
// 获取列表数据
const getComplainListData = async () =>{
try{
let params ={
status:currentTab.value,
villageId:uni.getStorageSync('currentVillageId')
}
const res = await getComplainList(params)
if(res.code === 200){
dataList.value = res.data.map(mapItem)
}else{
dataList.value = []
uni.showToast({title:res.msg || '获取失败',icon:'error'})
}
}catch(err){
// console.log('dess',err)
uni.showToast({title:err.msg || '网络异常',icon:'error'})
}finally{
uni.stopPullDownRefresh();
}
}
onLoad(() =>{
getComplainListData()
})
onShow(() => {
getComplainListData()
});
onPullDownRefresh(() => {
getComplainListData();
});
// 跳转到详情
const turnToDetail = (item) => {
uni.navigateTo({
url: `/pageSubPack/service-list/complaintsDetail?id=${item.id}&status=${item.status}`
})
}
// 新增投诉
const addComplaintsSuggestions = () => {
uni.navigateTo({
url: '/pageSubPack/service-list/addComplaints'
})
}
// 页面挂载后加载数据
// onMounted(() => {
// getDataList()
// })
</script>
<style lang="scss">
page {
background: #f2f1f6;
}
</style>
<style scoped>
.contentStyle {
min-height: 100vh;
background: linear-gradient(to left bottom, #e2efff 0%, #f9f9f9 50%);
}
.page {
padding: 0px 40rpx 200rpx;
box-sizing: border-box;
}
.page-container {
padding-top: 20rpx;
}
.empty-state {
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
padding: 100rpx 0;
color: #ccc;
}
.empty-text {
font-size: 28rpx;
color: #999;
margin-top: 20rpx;
margin-bottom: 10rpx;
}
.tab-wrap {
position: sticky;
top: 0;
z-index: 10;
background: #e2efff;
display: flex;
justify-content: flex-start;
align-items: center;
padding: 10rpx 40rpx 20rpx;
}
.tab-item {
position: relative;
padding: 10rpx 0;
margin-right: 80rpx;
}
.tab-item:last-child {
margin-right: 0;
}
.tab-text {
font-size: 30rpx;
color: #999;
}
.tab-item.active .tab-text {
color: #007AFF;
font-weight: 600;
}
.tab-item.active::after {
content: '';
position: absolute;
bottom: 0;
left: 50%;
transform: translateX(-50%);
width: 96rpx;
height: 4rpx;
background: #2F77FD;
border-radius: 32rpx;
}
.card-wrapper {
background: #ffffff;
border-radius: 16rpx;
padding: 30rpx;
box-shadow: 0 4rpx 12rpx rgba(0, 0, 0, 0.05);
margin-bottom: 20rpx;
}
.card-header {
display: flex;
align-items: center;
margin-bottom: 20rpx;
}
.card-title {
font-size: 32rpx;
font-weight: 400;
color: #222222;
margin-right: 20rpx;
}
.card-tag {
font-size: 24rpx;
padding: 2rpx 16rpx;
border-radius: 40rpx;
}
.pending {
background: #E34D59;
color: #FFFFFF;
}
.processing {
background: #09C2BD;
color: #FFFFFF;
}
.completed {
background: #2F77FD;
color: #FFFFFF;
}
.card-body {
display: flex;
flex-direction: column;
}
.card-desc {
font-size: 28rpx;
color: #666666;
line-height: 40rpx;
margin-bottom: 20rpx;
}
.img-scroll-container {
display: flex;
flex-wrap: wrap;
gap: 20rpx;
margin: 10rpx 0px 20rpx 0px;
}
.img-item {
width: calc(33.333% - 14rpx);
height: 52px;
}
.card-img {
width: 100%;
height: 56px;
object-fit: cover;
}
.card-footer {
display: flex;
justify-content: space-between;
align-items: center;
}
.card-time {
font-size: 24rpx;
color: #999999;
}
.card-detail {
font-size: 26rpx;
color: #2F77FD;
}
.bottom-btn-wrap {
position: fixed;
bottom: 0;
left: 0;
right: 0;
z-index: 10;
padding: 20rpx 30rpx 40rpx;
display: flex;
gap: 20rpx;
background: #f9f9f9;
}
.next-btn {
width: 100%;
height: 96rpx;
line-height: 96rpx;
background-color: #1677ff;
color: #fff;
font-size: 28rpx;
border-radius: 12rpx;
border: none;
}
</style>