You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

388 lines
8.3 KiB

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

<template>
<view class="container">
<!-- 状态筛选标签 -->
<u-tabs :list="statusTabs" :is-scroll="false" :current="currentStatusTab" @change="changeStatusTab"></u-tabs>
<view class="list-container">
<view v-if="loading && page === 1" class="loading-state">
<u-loading-page :loading="true"></u-loading-page>
</view>
<view v-else-if="list.length === 0 && !loading" class="empty-state">
<u-icon name="empty-data" size="120" color="#c0c4cc"></u-icon>
<text class="empty-text">您还没有发布任何供需信息</text>
<view class="empty-button" @click="goToPublish">
<text class="empty-button-text">立即发布</text>
</view>
</view>
<view v-else v-for="item in list" :key="item.id" class="list-item">
<view class="item-header">
<view :class="['type-badge', item.type === 1 ? 'supply' : 'demand']">{{ item.type === 1 ? '供应' : '需求' }}</view>
<view :class="['status-badge', getStatusClass(item.status)]">{{ getStatusText(item.status) }}</view>
<text class="time">{{ item.created_at }}</text>
</view>
<text class="item-title">{{ item.title }}</text>
<text class="description">{{ item.content }}</text>
<view class="tags" v-if="item.tag">
<text v-for="tag in item.tag.split(',')" :key="tag" class="tag">{{ tag }}</text>
</view>
<u-line color="#e8e8e8" margin="20rpx 0" />
<view class="item-footer">
<view class="stats">
<text class="stat-item">{{ item.view_count || 0 }}浏览</text>
<text class="stat-item">{{ item.contact_count || 0 }}私信</text>
</view>
<view class="actions">
<view class="view-button view-button-check" @click="goToDetail(item.id)">
<text class="button-text">查看</text>
</view>
<view v-if="item.status === 3 || item.status === 2" class="view-button view-button-edit" @click="goToEdit(item.id)">
<text class="button-text"></text>
</view>
</view>
</view>
</view>
<u-loadmore :status="status" nomore-text="~" />
</view>
</view>
</template>
<script>
import uLoadmore from '@/uview-ui/components/u-loadmore/u-loadmore.vue';
import uLine from '@/uview-ui/components/u-line/u-line.vue';
import uLoadingPage from '@/uview-ui/components/u-loading-page/u-loading-page.vue';
import uTabs from '@/uview-ui/components/u-tabs/u-tabs.vue';
import { base } from '@/common/util.js';
export default {
components: {
uLoadmore,
uLine,
uLoadingPage,
uTabs
},
data() {
return {
base,
list: [],
page: 1,
pageSize: 10,
status: 'loadmore',
loading: false,
currentStatusTab: 0, // 当前选中的状态标签
statusTabs: [
{ name: '全部' },
{ name: '已发布' },
{ name: '退回修改' },
{ name: '已拒绝' }
]
}
},
onLoad() {
this.fetchMyPosts();
},
onReachBottom() {
if (this.status === 'loadmore' && !this.loading) {
this.page++;
this.fetchMyPosts();
}
},
methods: {
fetchMyPosts() {
if (this.loading) return;
this.loading = true;
const params = {
page: this.page,
pageSize: this.pageSize,
myself: 1 // 1表示我的发布
};
// 根据状态标签索引映射到实际状态值
// 现在有4个状态标签全部、已发布、退回修改、已拒绝
if (this.currentStatusTab === 0) {
// 全部状态,传递-1表示不筛选状态
params.status = '-1';
} else {
const statusMap = {
1: 1, // 已发布状态为1
2: 3, // 退回修改状态为3
3: 2 // 已拒绝状态为2
};
params.status = statusMap[this.currentStatusTab] || 1;
}
this.$u.api.supplyDemandList(params).then(res => {
const supplyDemands = res.supplyDemands;
const newList = supplyDemands.data || [];
if (this.page === 1) {
this.list = newList;
} else {
this.list = [...this.list, ...newList];
}
// 判断是否还有更多数据
if (supplyDemands.current_page >= supplyDemands.last_page) {
this.status = 'nomore';
} else {
this.status = 'loadmore';
}
}).catch(err => {
console.error('获取我的发布列表失败:', err);
this.$u.toast('网络错误,请重试');
}).finally(() => {
this.loading = false;
});
},
goToDetail(id) {
uni.navigateTo({
url: `/packages/supply/detail?id=${id}`
})
},
goToEdit(id) {
// 跳转到编辑页面,这里可以根据实际需求实现
uni.navigateTo({
url: `/packages/supply/publish?id=${id}`
})
},
goToPublish() {
uni.navigateTo({
url: '/packages/supply/publish'
})
},
changeStatusTab(index) {
this.currentStatusTab = index;
this.page = 1;
this.list = [];
this.status = 'loadmore';
this.fetchMyPosts();
},
getStatusClass(status) {
switch (status) {
case 0:
return 'pending';
case 1:
return 'approved';
case 2:
return 'denied';
case 3:
return 'rejected';
case 4:
return 'hidden';
default:
return '';
}
},
getStatusText(status) {
switch (status) {
case 0:
return '待审核';
case 1:
return '审核通过';
case 2:
return '已拒绝';
case 3:
return '退回修改';
case 4:
return '永久隐藏';
default:
return '未知';
}
}
}
}
</script>
<style lang="scss" scoped>
.container {
background-color: #f5f5f5;
min-height: 100vh;
}
.header {
background: linear-gradient(to right, #e3ccb2, #cba579);
padding: 40rpx 30rpx;
text-align: center;
}
.item-title {
font-size: 32rpx;
font-weight: bold;
display: block;
margin-bottom: 10rpx;
color: #333;
}
.list-container {
background: linear-gradient(to bottom, #e9f2fa, #e9f2fa);
padding: 20rpx;
min-height: calc(100vh - 180rpx);
}
.list-item {
background-color: #fff;
border-radius: 20rpx;
padding: 25rpx;
margin-bottom: 20rpx;
}
.item-header {
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 15rpx;
}
.type-badge {
font-size: 24rpx;
padding: 8rpx 15rpx;
border-radius: 10rpx;
margin-right: 10rpx;
}
.supply {
background-color: #fff0e6;
color: #f29100;
}
.demand {
background-color: #e6f0ff;
color: #007aff;
}
.status-badge {
font-size: 24rpx;
padding: 8rpx 15rpx;
border-radius: 10rpx;
margin-right: 10rpx;
}
.status-badge.pending {
background-color: #fffbe6;
color: #f29100;
}
.status-badge.approved {
background-color: #e6ffe6;
color: #00c853;
}
.status-badge.rejected {
background-color: #ffe6e6;
color: #ff3b30;
}
.status-badge.hidden {
background-color: #f0f0f0;
color: #999;
}
.status-badge.denied {
background-color: #ffe6e6;
color: #d32f2f;
}
.time {
font-size: 24rpx;
color: #999;
}
.description {
font-size: 28rpx;
color: #666;
line-height: 1.6;
margin-bottom: 30rpx;
display: block;
max-height: 120rpx;
overflow: hidden;
}
.tags {
display: flex;
flex-wrap: wrap;
}
.tag {
background-color: #f5f5f5;
color: #666;
font-size: 24rpx;
padding: 8rpx 15rpx;
border-radius: 30rpx;
margin-right: 15rpx;
margin-bottom: 10rpx;
}
.item-footer {
display: flex;
justify-content: space-between;
align-items: center;
}
.stats {
display: flex;
gap: 20rpx;
}
.stat-item {
font-size: 24rpx;
color: #999;
}
.actions {
display: flex;
align-items: center;
}
.view-button {
width: 150rpx;
height: 60rpx;
border-radius: 30rpx;
display: flex;
align-items: center;
justify-content: center;
margin-left: 15rpx;
}
.view-button-check {
background: linear-gradient(to right, #e3ccb2, #cba579);
}
.view-button-edit {
background: linear-gradient(to right, #5d5ebc, #12099a);
}
.button-text {
color: white;
font-size: 26rpx;
}
.empty-state {
display: flex;
flex-direction: column;
align-items: center;
padding: 80rpx 0;
color: #c0c4cc;
}
.empty-text {
margin-top: 20rpx;
font-size: 32rpx;
color: #c0c4cc;
}
.empty-button {
margin-top: 40rpx;
width: 280rpx;
height: 80rpx;
background: linear-gradient(to right, #e3ccb2, #cba579);
border-radius: 40rpx;
display: flex;
align-items: center;
justify-content: center;
}
.empty-button-text {
color: white;
font-size: 32rpx;
}
</style>