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.

371 lines
7.9 KiB

<template>
<view class="container">
<view class="search-bar">
<view class="search-header">
<view class="my-posts-button" @click="toggleMyPosts">
<u-icon name="edit-pen" color="#fff" size="32"></u-icon>
<text class="my-posts-text">我发布的</text>
</view>
<view class="my-posts-button" @click="goToProfile">
<u-icon name="chat" color="#fff" size="32"></u-icon>
<text class="my-posts-text">我的私信</text>
</view>
<view class="search-input-container">
<u-search placeholder="请输入关键词" v-model="keyword" :show-action="false" @search="search" @input="onSearchInput"></u-search>
</view>
</view>
</view>
<u-tabs :list="tabs" :is-scroll="false" :current="currentTab" @change="changeTab"></u-tabs>
<view class="list-container">
<view 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>
<text class="time">{{ item.created_at }}</text>
</view>
<text class="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="user-info">
<u-avatar :src="item.user.headimgurl || ''" size="60"></u-avatar>
<text class="user-name">{{ item.user.name || '匿名用户' }}</text>
</view>
<view class="actions">
<view class="view-button view-button-check" @click="goToDetail(item.id)">
<text class="button-text">查看</text>
</view>
<view class="view-button view-button-msg" @click="goToChat(item)">
<text class="button-text">私信</text>
</view>
</view>
</view>
</view>
<u-loadmore :status="status" nomore-text="已经到底了~" />
</view>
<image class="publish-image" :src="base.imgHost('publish.png')" @click="goToPublish"></image>
</view>
</template>
<script>
import uSearch from '@/uview-ui/components/u-search/u-search.vue';
import uLoadmore from '@/uview-ui/components/u-loadmore/u-loadmore.vue';
import uTabs from '@/uview-ui/components/u-tabs/u-tabs.vue';
import uLine from '@/uview-ui/components/u-line/u-line.vue';
import uAvatar from '@/uview-ui/components/u-avatar/u-avatar.vue';
import { base } from '@/common/util.js';
export default {
components: {
uSearch,
uLoadmore,
uTabs,
uLine,
uAvatar
},
data() {
return {
base,
keyword: '',
currentTab: 0,
tabs: [{
name: '全部'
}, {
name: '供应'
}, {
name: '需求'
}],
list: [],
page: 1,
pageSize: 10,
status: 'loadmore',
loading: false
}
},
onLoad() {
this.fetchList();
},
onReachBottom() {
if (this.status === 'loadmore' && !this.loading) {
this.page++;
this.fetchList();
}
},
watch: {
keyword(newVal, oldVal) {
// 当关键词被清空时,自动刷新数据
if (oldVal && !newVal) {
this.page = 1;
this.list = [];
this.status = 'loadmore';
this.fetchList();
}
}
},
methods: {
goToProfile() {
uni.navigateTo({
url: '/packages/chat/index'
});
},
changeTab(index) {
this.currentTab = index;
this.page = 1;
this.list = [];
this.status = 'loadmore';
this.fetchList();
},
search() {
this.page = 1;
this.list = [];
this.status = 'loadmore';
this.fetchList();
},
onSearchInput(value) {
// 当输入框内容变化时,可以在这里添加防抖逻辑
// 目前 watch 已经处理了清空的情况
},
fetchList() {
if (this.loading) return;
this.loading = true;
const params = {
page: this.page,
pageSize: this.pageSize
};
// 根据当前tab设置type参数
if (this.currentTab === 1) {
params.type = 1; // 供应
} else if (this.currentTab === 2) {
params.type = 2; // 需求
}
// 如果有搜索关键词
if (this.keyword) {
params.keyword = this.keyword;
}
this.$u.api.supplyDemandList(params).then(res => {
// res 直接就是 supplyDemands 对象
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;
});
},
goToPublish() {
uni.navigateTo({
url: '/packages/supply/publish'
})
},
goToDetail(id) {
uni.navigateTo({
url: `/packages/supply/detail?id=${id}`
})
},
goToChat(item) {
// 传递用户信息到聊天页面
uni.navigateTo({
url: `/packages/chat/chatWindow?userId=${item.user_id}&userName=${item.user.name}&supplyDemandId=${item.id}`
})
},
toggleMyPosts() {
// 跳转到我的发布页面
uni.navigateTo({
url: '/packages/supply/my-posts'
})
}
}
}
</script>
<style lang="scss" scoped>
.container {
background-color: #f5f5f5;
min-height: 100vh;
}
.search-bar {
padding: 20rpx;
background-color: #fff;
}
.search-header {
display: flex;
align-items: center;
gap: 20rpx;
margin-bottom: 20rpx;
}
.my-posts-button {
display: flex;
align-items: center;
background: linear-gradient(to right, #e3ccb2, #cba579);
padding: 20rpx 30rpx;
border-radius: 60rpx;
box-shadow: 0 4rpx 12rpx rgba(203, 165, 121, 0.3);
transition: all 0.3s ease;
}
.my-posts-button:active {
transform: scale(0.95);
}
.my-posts-text {
color: #fff;
font-size: 28rpx;
font-weight: 500;
margin-left: 10rpx;
}
.search-input-container {
flex: 1;
}
.list-container {
background: linear-gradient(to bottom, #e9f2fa, #e9f2fa);
padding: 20rpx;
min-height: calc(100vh - 180rpx);
/* Adjust as needed */
}
.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;
}
.supply {
background-color: #fff0e6;
color: #f29100;
}
.demand {
background-color: #e6f0ff;
color: #007aff;
}
.time {
font-size: 24rpx;
color: #999;
}
.title {
font-size: 32rpx;
font-weight: bold;
display: block;
margin-bottom: 10rpx;
}
.description {
font-size: 28rpx;
color: #666;
line-height: 1.6;
margin-bottom: 30rpx;
display: block;
max-height: 120rpx; /* 约3行文字的高度 */
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;
}
.user-info {
display: flex;
align-items: center;
}
.user-name {
font-size: 28rpx;
margin-left: 15rpx;
}
.actions {
display: flex;
align-items: center;
}
.view-button {
width: 150rpx;
height: 60rpx;
border-radius: 30rpx;
display: flex;
align-items: center;
justify-content: center;
}
.view-button-check {
background: linear-gradient(to right, #e3ccb2, #cba579);
margin-right: 20rpx;
}
.view-button-msg {
background: linear-gradient(to right, #5d5ebc, #12099a);
}
.button-text {
color: white;
font-size: 26rpx;
}
.publish-image {
position: fixed;
bottom: 80rpx;
right: 0rpx;
width: 180rpx;
height: 140rpx;
z-index: 99;
}
</style>