|
|
|
|
@ -1,31 +1,31 @@
|
|
|
|
|
<template>
|
|
|
|
|
<view class="container">
|
|
|
|
|
<view class="search-bar">
|
|
|
|
|
<u-search placeholder="请输入关键词" v-model="keyword" :show-action="false"></u-search>
|
|
|
|
|
<u-search placeholder="请输入关键词" v-model="keyword" :show-action="false" @search="search" @input="onSearchInput"></u-search>
|
|
|
|
|
</view>
|
|
|
|
|
<u-tabs :list="tabs" :is-scroll="false" :current="currentTab" @change="changeTab"></u-tabs>
|
|
|
|
|
<view class="list-container">
|
|
|
|
|
<view v-for="item in filteredList" :key="item.id" class="list-item">
|
|
|
|
|
<view v-for="item in list" :key="item.id" class="list-item">
|
|
|
|
|
<view class="item-header">
|
|
|
|
|
<view :class="['type-badge', item.type === 'supply' ? 'supply' : 'demand']">{{ item.type === 'supply' ? '供应' : '需求' }}</view>
|
|
|
|
|
<text class="time">{{ item.time }}</text>
|
|
|
|
|
<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.description }}</text>
|
|
|
|
|
<view class="tags">
|
|
|
|
|
<text v-for="tag in item.tags" :key="tag" class="tag">{{ tag }}</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.avatar" size="60"></u-avatar>
|
|
|
|
|
<text class="user-name">{{ item.user.name }}</text>
|
|
|
|
|
<u-avatar :src="item.user_avatar || 'https://via.placeholder.com/60'" 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.user)">
|
|
|
|
|
<view class="view-button view-button-msg" @click="goToChat(item)">
|
|
|
|
|
<text class="button-text">私信</text>
|
|
|
|
|
</view>
|
|
|
|
|
</view>
|
|
|
|
|
@ -40,13 +40,22 @@
|
|
|
|
|
<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
|
|
|
|
|
uLoadmore,
|
|
|
|
|
uTabs,
|
|
|
|
|
uLine,
|
|
|
|
|
uAvatar
|
|
|
|
|
},
|
|
|
|
|
data() {
|
|
|
|
|
return {
|
|
|
|
|
base,
|
|
|
|
|
keyword: '',
|
|
|
|
|
currentTab: 0,
|
|
|
|
|
tabs: [{
|
|
|
|
|
@ -56,52 +65,96 @@
|
|
|
|
|
}, {
|
|
|
|
|
name: '需求'
|
|
|
|
|
}],
|
|
|
|
|
list: [{
|
|
|
|
|
id: 1,
|
|
|
|
|
type: 'supply',
|
|
|
|
|
time: '2小时前',
|
|
|
|
|
title: '提供企业管理咨询服务',
|
|
|
|
|
description: '专业企业管理咨询团队,具有10年以上行业经验,擅长企业战略规划、组织架构优化、流程梳理等。已服务过多家上市公司...',
|
|
|
|
|
tags: ['管理咨询', '战略规划', '管理咨询'],
|
|
|
|
|
user: {
|
|
|
|
|
name: '张云',
|
|
|
|
|
avatar: 'https://via.placeholder.com/60'
|
|
|
|
|
}
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
id: 2,
|
|
|
|
|
type: 'demand',
|
|
|
|
|
time: '2小时前',
|
|
|
|
|
title: '提供企业管理咨询服务',
|
|
|
|
|
description: '我们是一家初创公司,目前在开发一款AI智能客服产品,需要寻找有经验的技术合作伙伴,共同推进项目发展...',
|
|
|
|
|
tags: ['AI', '技术合作', '客服系统'],
|
|
|
|
|
user: {
|
|
|
|
|
name: '李经理',
|
|
|
|
|
avatar: 'https://via.placeholder.com/60'
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
],
|
|
|
|
|
status: 'nomore'
|
|
|
|
|
list: [],
|
|
|
|
|
page: 1,
|
|
|
|
|
pageSize: 10,
|
|
|
|
|
status: 'loadmore',
|
|
|
|
|
loading: false
|
|
|
|
|
}
|
|
|
|
|
},
|
|
|
|
|
computed: {
|
|
|
|
|
filteredList() {
|
|
|
|
|
let list = this.list;
|
|
|
|
|
if (this.currentTab === 1) {
|
|
|
|
|
list = list.filter(item => item.type === 'supply');
|
|
|
|
|
} else if (this.currentTab === 2) {
|
|
|
|
|
list = list.filter(item => item.type === 'demand');
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (this.keyword) {
|
|
|
|
|
list = list.filter(item => item.title.includes(this.keyword) || item.description.includes(this.keyword));
|
|
|
|
|
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();
|
|
|
|
|
}
|
|
|
|
|
return list;
|
|
|
|
|
}
|
|
|
|
|
},
|
|
|
|
|
methods: {
|
|
|
|
|
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({
|
|
|
|
|
@ -113,10 +166,10 @@
|
|
|
|
|
url: `/packages/supply/detail?id=${id}`
|
|
|
|
|
})
|
|
|
|
|
},
|
|
|
|
|
goToChat(user) {
|
|
|
|
|
// 假设私信需要用户id
|
|
|
|
|
goToChat(item) {
|
|
|
|
|
// 传递用户信息到聊天页面
|
|
|
|
|
uni.navigateTo({
|
|
|
|
|
url: `/packages/chat/chatWindow?userId=${user.id}`
|
|
|
|
|
url: `/packages/chat/chatWindow?userId=${item.user_id}&userName=${item.user_name}`
|
|
|
|
|
})
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
@ -189,6 +242,8 @@
|
|
|
|
|
line-height: 1.6;
|
|
|
|
|
margin-bottom: 30rpx;
|
|
|
|
|
display: block;
|
|
|
|
|
max-height: 120rpx; /* 约3行文字的高度 */
|
|
|
|
|
overflow: hidden;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.tags {
|
|
|
|
|
|