|
|
@@ -11,39 +11,64 @@
|
|
|
<view class="search-bar">
|
|
|
<view class="search-input-wrapper">
|
|
|
<view class="search-icon-small"></view>
|
|
|
- <input type="text" class="search-input" placeholder="请输入搜索关键词" placeholder-style="color: #999;" />
|
|
|
+ <input type="text" class="search-input" placeholder="请输入搜索关键词" placeholder-style="color: #999;" v-model="searchKeyword" @input="handleSearch" />
|
|
|
</view>
|
|
|
</view>
|
|
|
|
|
|
<!-- 资源列表 -->
|
|
|
- <scroll-view scroll-y class="content">
|
|
|
- <view class="resource-item" v-for="(resource, index) in resources" :key="index">
|
|
|
+ <scroll-view scroll-y class="content" @scrolltolower="loadMore" :scroll-with-animation="true">
|
|
|
+ <view v-if="loading" class="loading-wrapper">
|
|
|
+ <text class="loading-text">加载中...</text>
|
|
|
+ </view>
|
|
|
+ <view v-else-if="resources.length === 0" class="empty-wrapper">
|
|
|
+ <text class="empty-text">暂无优质资源</text>
|
|
|
+ </view>
|
|
|
+ <view class="resource-item" v-for="(resource, index) in resources" :key="getResourceKey(resource, index)" @click="handleResourceClick(index)">
|
|
|
<view class="resource-header">
|
|
|
- <view class="avatar"></view>
|
|
|
+ <image
|
|
|
+ :src="getAvatarUrl(resource) || '/static/default-avatar.svg'"
|
|
|
+ mode="aspectFill"
|
|
|
+ class="avatar"
|
|
|
+ @error="handleImageError(index)"
|
|
|
+ ></image>
|
|
|
<view class="resource-info">
|
|
|
<view class="name-gender">
|
|
|
<text class="name">{{ resource.name }}</text>
|
|
|
- <text class="gender">{{ resource.gender }}</text>
|
|
|
- <text class="status">{{ resource.status }}</text>
|
|
|
+ <text class="gender">{{ resource.gender === 1 ? '男' : '女' }}</text>
|
|
|
</view>
|
|
|
- <view class="tags">
|
|
|
- <view class="tag" v-for="(tag, tagIndex) in resource.tags" :key="tagIndex">{{ tag }}</view>
|
|
|
+ <view class="status-tag-wrapper">
|
|
|
+ <text class="status-tag register-tag registered">已注册</text>
|
|
|
+ <text class="status-tag match-tag" :class="{ 'matched': getIsMatch(resource) === 1, 'unmatched': getIsMatch(resource) === 0 || !getIsMatch(resource) }">
|
|
|
+ {{ getIsMatch(resource) === 1 ? '已匹配' : '未匹配' }}
|
|
|
+ </text>
|
|
|
</view>
|
|
|
</view>
|
|
|
</view>
|
|
|
<view class="resource-details">
|
|
|
- <view class="requirement">
|
|
|
+ <view class="labels" v-if="resource.tags && resource.tags.length > 0">
|
|
|
+ <text class="label" v-for="(tag, tagIndex) in resource.tags" :key="tagIndex">{{ tag }}</text>
|
|
|
+ </view>
|
|
|
+ <view class="requirement-box">
|
|
|
<text class="requirement-label">择偶要求:</text>
|
|
|
- <text class="requirement-content">{{ resource.requirement }}</text>
|
|
|
+ <text class="requirement-content">{{ getMateSelectionCriteria(resource) || '暂无' }}</text>
|
|
|
</view>
|
|
|
- <view class="contact-info">
|
|
|
+ <view class="contact-box">
|
|
|
<text class="contact-label">联系方式:</text>
|
|
|
- <text class="contact-number">{{ resource.contact }}</text>
|
|
|
- <view class="copy-btn" @click="handleCopy(resource.contact)">复制</view>
|
|
|
+ <text class="contact-number">{{ getMaskedPhone(resource.phone) || '暂无' }}</text>
|
|
|
+ <text class="copy-btn" @click.stop="handleCopy(resource.phone)">复制</text>
|
|
|
+ </view>
|
|
|
+ <view class="action-buttons">
|
|
|
+ <view class="action-btn add-resource-btn" @click.stop="handleAddToMyResources(index)">添加到我的资源</view>
|
|
|
+ <view class="action-btn chat-btn" @click.stop="handleChat(resource)">牵线聊聊</view>
|
|
|
</view>
|
|
|
- <view class="action-btn" @click="handleChat(resource)">牵线聊聊</view>
|
|
|
</view>
|
|
|
</view>
|
|
|
+ <view v-if="hasMore && !loading" class="load-more-wrapper">
|
|
|
+ <text class="load-more-text">上拉加载更多</text>
|
|
|
+ </view>
|
|
|
+ <view v-if="!hasMore && resources.length > 0" class="no-more-wrapper">
|
|
|
+ <text class="no-more-text">没有更多数据了</text>
|
|
|
+ </view>
|
|
|
</scroll-view>
|
|
|
</view>
|
|
|
</template>
|
|
|
@@ -53,34 +78,27 @@ export default {
|
|
|
name: 'quality-resources',
|
|
|
data() {
|
|
|
return {
|
|
|
- resources: [
|
|
|
- {
|
|
|
- name: '小高',
|
|
|
- gender: '男',
|
|
|
- status: '未匹配',
|
|
|
- tags: ['气质男', '小清新'],
|
|
|
- requirement: '165+ 本科',
|
|
|
- contact: '123****8912'
|
|
|
- },
|
|
|
- {
|
|
|
- name: '小子',
|
|
|
- gender: '男',
|
|
|
- status: '未匹配',
|
|
|
- tags: ['周末有空'],
|
|
|
- requirement: '165+ 本科',
|
|
|
- contact: '123****8912'
|
|
|
- },
|
|
|
- {
|
|
|
- name: '小博',
|
|
|
- gender: '男',
|
|
|
- status: '未匹配',
|
|
|
- tags: ['电话联系', '优质男'],
|
|
|
- requirement: '180+ 本科',
|
|
|
- contact: '123****8912'
|
|
|
- }
|
|
|
- ]
|
|
|
+ resources: [],
|
|
|
+ searchKeyword: '',
|
|
|
+ pageNum: 1,
|
|
|
+ pageSize: 10,
|
|
|
+ loading: false,
|
|
|
+ hasMore: true,
|
|
|
+ currentUserId: null // 当前登录用户的用户ID
|
|
|
}
|
|
|
},
|
|
|
+ onLoad() {
|
|
|
+ // 获取当前登录用户的ID
|
|
|
+ const userId = uni.getStorageSync('userId')
|
|
|
+ if (userId) {
|
|
|
+ const rawUserId = parseInt(userId)
|
|
|
+ if (!isNaN(rawUserId) && rawUserId > 0) {
|
|
|
+ this.currentUserId = rawUserId
|
|
|
+ console.log('当前登录用户ID:', this.currentUserId)
|
|
|
+ }
|
|
|
+ }
|
|
|
+ this.loadResources()
|
|
|
+ },
|
|
|
methods: {
|
|
|
// 返回上一页
|
|
|
handleBack() {
|
|
|
@@ -90,8 +108,125 @@ export default {
|
|
|
handleFilter() {
|
|
|
// 实现筛选功能
|
|
|
},
|
|
|
+ // 搜索
|
|
|
+ handleSearch() {
|
|
|
+ this.pageNum = 1
|
|
|
+ this.resources = []
|
|
|
+ this.hasMore = true
|
|
|
+ this.loadResources()
|
|
|
+ },
|
|
|
+ // 加载资源列表
|
|
|
+ async loadResources() {
|
|
|
+ if (this.loading) return
|
|
|
+
|
|
|
+ try {
|
|
|
+ this.loading = true
|
|
|
+ const baseUrl = process.env.NODE_ENV === 'development'
|
|
|
+ ? 'http://localhost:8083/api' // 开发环境 - 通过网关
|
|
|
+ : 'https://your-domain.com/api' // 生产环境
|
|
|
+
|
|
|
+ // 构建请求参数
|
|
|
+ const requestData = {
|
|
|
+ tagName: '优质资源',
|
|
|
+ keyword: this.searchKeyword || '',
|
|
|
+ pageNum: this.pageNum,
|
|
|
+ pageSize: this.pageSize
|
|
|
+ }
|
|
|
+
|
|
|
+ // 如果已登录,传递currentUserId,用于排除该红娘已拥有的资源
|
|
|
+ if (this.currentUserId) {
|
|
|
+ requestData.currentUserId = this.currentUserId
|
|
|
+ }
|
|
|
+
|
|
|
+ const [error, res] = await uni.request({
|
|
|
+ url: `${baseUrl}/my-resource/list-by-tag`,
|
|
|
+ method: 'GET',
|
|
|
+ data: requestData,
|
|
|
+ timeout: 10000
|
|
|
+ })
|
|
|
+
|
|
|
+ if (error) {
|
|
|
+ console.error('加载优质资源失败:', error)
|
|
|
+ uni.showToast({
|
|
|
+ title: '加载失败',
|
|
|
+ icon: 'none'
|
|
|
+ })
|
|
|
+ return
|
|
|
+ }
|
|
|
+
|
|
|
+ if (res.statusCode === 200 && res.data && res.data.code === 200) {
|
|
|
+ const pageData = res.data.data
|
|
|
+ if (pageData && pageData.records) {
|
|
|
+ // 调试:打印第一条数据的详细信息
|
|
|
+ if (pageData.records.length > 0) {
|
|
|
+ const firstRecord = pageData.records[0]
|
|
|
+ console.log('=== 第一条资源数据 ===')
|
|
|
+ console.log('完整数据:', JSON.stringify(firstRecord, null, 2))
|
|
|
+ console.log('isUser值:', firstRecord.isUser, '类型:', typeof firstRecord.isUser)
|
|
|
+ console.log('is_user值:', firstRecord.is_user, '类型:', typeof firstRecord.is_user)
|
|
|
+ console.log('userId值:', firstRecord.userId, '类型:', typeof firstRecord.userId)
|
|
|
+ console.log('user_id值:', firstRecord.user_id, '类型:', typeof firstRecord.user_id)
|
|
|
+ console.log('mateSelectionCriteria (驼峰):', firstRecord.mateSelectionCriteria)
|
|
|
+ console.log('mate_selection_criteria (下划线):', firstRecord.mate_selection_criteria)
|
|
|
+ console.log('phone:', firstRecord.phone)
|
|
|
+ }
|
|
|
+
|
|
|
+ if (this.pageNum === 1) {
|
|
|
+ this.resources = pageData.records
|
|
|
+ } else {
|
|
|
+ this.resources = this.resources.concat(pageData.records)
|
|
|
+ }
|
|
|
+
|
|
|
+ // 判断是否还有更多数据
|
|
|
+ this.hasMore = pageData.records && pageData.records.length >= this.pageSize
|
|
|
+
|
|
|
+ console.log('加载优质资源成功,数量:', this.resources.length)
|
|
|
+ } else {
|
|
|
+ console.error('加载优质资源失败:', res.data.message)
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ console.error('加载优质资源失败:', res.data.message)
|
|
|
+ uni.showToast({
|
|
|
+ title: res.data.message || '加载失败',
|
|
|
+ icon: 'none'
|
|
|
+ })
|
|
|
+ }
|
|
|
+ } catch (e) {
|
|
|
+ console.error('加载优质资源异常:', e)
|
|
|
+ uni.showToast({
|
|
|
+ title: '加载异常',
|
|
|
+ icon: 'none'
|
|
|
+ })
|
|
|
+ } finally {
|
|
|
+ this.loading = false
|
|
|
+ }
|
|
|
+ },
|
|
|
+ // 加载更多
|
|
|
+ loadMore() {
|
|
|
+ if (this.hasMore && !this.loading) {
|
|
|
+ this.pageNum++
|
|
|
+ this.loadResources()
|
|
|
+ }
|
|
|
+ },
|
|
|
+ // 图片加载错误处理
|
|
|
+ handleImageError(index) {
|
|
|
+ if (this.resources[index]) {
|
|
|
+ // 设置头像为空,让CSS默认背景显示
|
|
|
+ // 支持下划线和驼峰两种格式
|
|
|
+ this.resources[index].avatarUrl = ''
|
|
|
+ this.resources[index].avatar_url = ''
|
|
|
+ this.resources[index].avatar = ''
|
|
|
+ }
|
|
|
+ },
|
|
|
// 复制联系方式
|
|
|
handleCopy(contact) {
|
|
|
+ if (!contact) {
|
|
|
+ uni.showToast({
|
|
|
+ title: '联系方式为空',
|
|
|
+ icon: 'none'
|
|
|
+ })
|
|
|
+ return
|
|
|
+ }
|
|
|
uni.setClipboardData({
|
|
|
data: contact,
|
|
|
success: () => {
|
|
|
@@ -104,11 +239,424 @@ export default {
|
|
|
},
|
|
|
// 牵线聊聊
|
|
|
handleChat(resource) {
|
|
|
- // 跳转到聊天页面或打开聊天弹窗
|
|
|
- uni.showToast({
|
|
|
- title: '牵线成功',
|
|
|
- icon: 'success'
|
|
|
+ console.log('=== 牵线聊聊 ===')
|
|
|
+ console.log('资源信息:', resource)
|
|
|
+ console.log('资源信息类型:', typeof resource)
|
|
|
+ console.log('资源信息的所有键:', resource ? Object.keys(resource) : 'resource为空')
|
|
|
+
|
|
|
+ // 验证 resource 对象是否存在
|
|
|
+ if (!resource) {
|
|
|
+ console.error('❌ resource对象为空')
|
|
|
+ uni.showToast({
|
|
|
+ title: '资源信息为空',
|
|
|
+ icon: 'none'
|
|
|
+ })
|
|
|
+ return
|
|
|
+ }
|
|
|
+
|
|
|
+ // 检查用户是否已注册(只有已注册用户才能聊天)
|
|
|
+ // 支持下划线和驼峰两种格式
|
|
|
+ const isUser = resource.isUser !== undefined ? resource.isUser :
|
|
|
+ (resource.is_user !== undefined ? resource.is_user : 0)
|
|
|
+ if (isUser !== 1 && isUser !== '1') {
|
|
|
+ console.warn('⚠️ 用户未注册,无法聊天')
|
|
|
+ uni.showToast({
|
|
|
+ title: '该用户尚未注册,无法聊天',
|
|
|
+ icon: 'none',
|
|
|
+ duration: 3000
|
|
|
+ })
|
|
|
+ return
|
|
|
+ }
|
|
|
+
|
|
|
+ // 尝试多种方式获取用户ID
|
|
|
+ let targetUserId = null
|
|
|
+
|
|
|
+ // 方式1: 使用 userId 字段(驼峰格式)
|
|
|
+ if (resource.userId !== null && resource.userId !== undefined && resource.userId !== '') {
|
|
|
+ targetUserId = String(resource.userId)
|
|
|
+ console.log('✅ 从 resource.userId 获取用户ID:', targetUserId)
|
|
|
+ }
|
|
|
+ // 方式2: 使用 user_id 字段(下划线格式)
|
|
|
+ else if (resource.user_id !== null && resource.user_id !== undefined && resource.user_id !== '') {
|
|
|
+ targetUserId = String(resource.user_id)
|
|
|
+ console.log('✅ 从 resource.user_id 获取用户ID:', targetUserId)
|
|
|
+ }
|
|
|
+ // 方式3: 使用 id 字段
|
|
|
+ else if (resource.id !== null && resource.id !== undefined && resource.id !== '') {
|
|
|
+ targetUserId = String(resource.id)
|
|
|
+ console.log('✅ 从 resource.id 获取用户ID:', targetUserId)
|
|
|
+ }
|
|
|
+
|
|
|
+ // 如果仍然没有获取到用户ID
|
|
|
+ if (!targetUserId || targetUserId === 'null' || targetUserId === 'undefined' || targetUserId === '') {
|
|
|
+ console.error('❌ 无法获取用户ID')
|
|
|
+ console.log('resource对象完整内容:', JSON.stringify(resource, null, 2))
|
|
|
+ uni.showToast({
|
|
|
+ title: '无法获取用户ID,请刷新重试',
|
|
|
+ icon: 'none',
|
|
|
+ duration: 3000
|
|
|
+ })
|
|
|
+ return
|
|
|
+ }
|
|
|
+
|
|
|
+ // 获取其他必要信息(支持下划线和驼峰格式)
|
|
|
+ const targetUserName = resource.name || '用户'
|
|
|
+ const targetUserAvatar = resource.avatarUrl || resource.avatar_url || resource.avatar || '/static/default-avatar.svg'
|
|
|
+
|
|
|
+ console.log('跳转参数:')
|
|
|
+ console.log(' - targetUserId:', targetUserId)
|
|
|
+ console.log(' - targetUserName:', targetUserName)
|
|
|
+ console.log(' - targetUserAvatar:', targetUserAvatar)
|
|
|
+
|
|
|
+ // 跳转到聊天页面
|
|
|
+ // 注意:fromMatchmaker=1 表示来自红娘工作台,会跳过消息限制和审核
|
|
|
+ uni.navigateTo({
|
|
|
+ url: `/pages/message/chat?targetUserId=${targetUserId}&targetUserName=${encodeURIComponent(targetUserName)}&targetUserAvatar=${encodeURIComponent(targetUserAvatar)}&fromMatchmaker=1`,
|
|
|
+ success: () => {
|
|
|
+ console.log('✅ 跳转聊天页面成功')
|
|
|
+ },
|
|
|
+ fail: (err) => {
|
|
|
+ console.error('❌ 跳转聊天页面失败:', err)
|
|
|
+ uni.showToast({
|
|
|
+ title: '跳转失败,请重试',
|
|
|
+ icon: 'none'
|
|
|
+ })
|
|
|
+ }
|
|
|
})
|
|
|
+ },
|
|
|
+ // 获取资源项的key(用于v-for)
|
|
|
+ getResourceKey(resource, index) {
|
|
|
+ if (!resource) return `resource-${index}`
|
|
|
+ // 支持下划线和驼峰两种格式
|
|
|
+ const resourceId = resource.resourceId || resource.resource_id
|
|
|
+ if (resourceId !== null && resourceId !== undefined && resourceId !== '') {
|
|
|
+ return `resource-${resourceId}`
|
|
|
+ }
|
|
|
+ return `resource-${index}`
|
|
|
+ },
|
|
|
+ // 点击资源项
|
|
|
+ handleResourceClick(index) {
|
|
|
+ console.log('=== 点击资源项 ===')
|
|
|
+ console.log('传入的index:', index)
|
|
|
+ console.log('resources数组长度:', this.resources.length)
|
|
|
+
|
|
|
+ // 检查index是否有效
|
|
|
+ if (index === undefined || index === null || index < 0 || index >= this.resources.length) {
|
|
|
+ console.error('❌ index无效:', index)
|
|
|
+ uni.showToast({
|
|
|
+ title: '资源索引无效',
|
|
|
+ icon: 'none'
|
|
|
+ })
|
|
|
+ return
|
|
|
+ }
|
|
|
+
|
|
|
+ // 从数组中获取resource对象
|
|
|
+ const resource = this.resources[index]
|
|
|
+ console.log('从数组获取的resource对象:', JSON.stringify(resource, null, 2))
|
|
|
+
|
|
|
+ if (!resource) {
|
|
|
+ console.error('❌ resource对象为空')
|
|
|
+ uni.showToast({
|
|
|
+ title: '资源信息为空',
|
|
|
+ icon: 'none'
|
|
|
+ })
|
|
|
+ return
|
|
|
+ }
|
|
|
+
|
|
|
+ // 支持下划线和驼峰两种格式
|
|
|
+ const resourceId = resource.resourceId || resource.resource_id
|
|
|
+ const isUser = resource.isUser !== undefined ? resource.isUser :
|
|
|
+ (resource.is_user !== undefined ? resource.is_user : 0)
|
|
|
+
|
|
|
+ console.log('resource.resourceId:', resourceId)
|
|
|
+ console.log('resource.isUser:', isUser)
|
|
|
+
|
|
|
+ // 检查resourceId是否有效
|
|
|
+ if (!resourceId || resourceId === null || resourceId === undefined || resourceId === '') {
|
|
|
+ console.error('❌ resourceId无效:', resourceId)
|
|
|
+ uni.showToast({
|
|
|
+ title: '资源ID无效,无法查看详情',
|
|
|
+ icon: 'none'
|
|
|
+ })
|
|
|
+ return
|
|
|
+ }
|
|
|
+
|
|
|
+ // 判断是否为已注册用户
|
|
|
+ if (isUser === 1 || isUser === '1') {
|
|
|
+ // 已注册,跳转到客户详情页面,添加fromQualityResources参数标识来源
|
|
|
+ console.log('准备跳转,resourceId:', resourceId)
|
|
|
+ uni.navigateTo({
|
|
|
+ url: `/pages/matchmaker-workbench/client-detail?resourceId=${resourceId}&fromQualityResources=1`,
|
|
|
+ success: () => {
|
|
|
+ console.log('✅ 跳转成功,resourceId:', resourceId)
|
|
|
+ },
|
|
|
+ fail: (err) => {
|
|
|
+ console.error('❌ 跳转失败:', err)
|
|
|
+ uni.showToast({
|
|
|
+ title: '跳转失败,请重试',
|
|
|
+ icon: 'none'
|
|
|
+ })
|
|
|
+ }
|
|
|
+ })
|
|
|
+ } else {
|
|
|
+ // 未注册,提示用户(虽然后端已经过滤了,但为了容错仍然保留)
|
|
|
+ uni.showToast({
|
|
|
+ title: '该用户还未注册用户端',
|
|
|
+ icon: 'none',
|
|
|
+ duration: 2000
|
|
|
+ })
|
|
|
+ }
|
|
|
+ },
|
|
|
+ // 添加到我的资源
|
|
|
+ async handleAddToMyResources(index) {
|
|
|
+ console.log('=== 添加到我的资源 ===')
|
|
|
+ console.log('index:', index)
|
|
|
+
|
|
|
+ // 检查index是否有效
|
|
|
+ if (index === undefined || index === null || index < 0 || index >= this.resources.length) {
|
|
|
+ console.error('❌ index无效:', index)
|
|
|
+ uni.showToast({
|
|
|
+ title: '资源索引无效',
|
|
|
+ icon: 'none'
|
|
|
+ })
|
|
|
+ return
|
|
|
+ }
|
|
|
+
|
|
|
+ // 从数组中获取resource对象
|
|
|
+ const resource = this.resources[index]
|
|
|
+ console.log('从数组获取的resource对象:', JSON.stringify(resource, null, 2))
|
|
|
+
|
|
|
+ if (!resource) {
|
|
|
+ console.error('❌ resource对象为空')
|
|
|
+ uni.showToast({
|
|
|
+ title: '资源信息为空',
|
|
|
+ icon: 'none'
|
|
|
+ })
|
|
|
+ return
|
|
|
+ }
|
|
|
+
|
|
|
+ // 检查是否已登录
|
|
|
+ if (!this.currentUserId) {
|
|
|
+ uni.showToast({
|
|
|
+ title: '请先登录',
|
|
|
+ icon: 'none'
|
|
|
+ })
|
|
|
+ return
|
|
|
+ }
|
|
|
+
|
|
|
+ try {
|
|
|
+ uni.showLoading({
|
|
|
+ title: '添加中...'
|
|
|
+ })
|
|
|
+
|
|
|
+ const baseUrl = process.env.NODE_ENV === 'development'
|
|
|
+ ? 'http://localhost:8083/api' // 开发环境 - 通过网关
|
|
|
+ : 'https://your-domain.com/api' // 生产环境
|
|
|
+
|
|
|
+ // 构建要添加的资源数据(复制原资源的所有信息,但使用当前红娘的matchmaker_id)
|
|
|
+ const resourceData = {
|
|
|
+ name: resource.name,
|
|
|
+ age: resource.age,
|
|
|
+ gender: resource.gender,
|
|
|
+ constellation: resource.constellation,
|
|
|
+ height: resource.height,
|
|
|
+ weight: resource.weight,
|
|
|
+ marrStatus: resource.marrStatus || resource.marr_status,
|
|
|
+ diploma: resource.diploma,
|
|
|
+ income: resource.income,
|
|
|
+ address: resource.address,
|
|
|
+ domicile: resource.domicile,
|
|
|
+ occupation: resource.occupation,
|
|
|
+ house: resource.house,
|
|
|
+ phone: resource.phone,
|
|
|
+ backupPhone: resource.backupPhone || resource.backup_phone,
|
|
|
+ car: resource.car,
|
|
|
+ mateSelectionCriteria: resource.mateSelectionCriteria || resource.mate_selection_criteria,
|
|
|
+ isUser: resource.isUser || resource.is_user || 1,
|
|
|
+ userId: resource.userId || resource.user_id
|
|
|
+ }
|
|
|
+
|
|
|
+ // 获取标签ID列表
|
|
|
+ let tagIds = []
|
|
|
+
|
|
|
+ // 方法1: 如果resource有resourceId,直接根据resourceId获取标签ID
|
|
|
+ const resourceId = resource.resourceId || resource.resource_id
|
|
|
+ if (resourceId) {
|
|
|
+ try {
|
|
|
+ const [tagError, tagRes] = await uni.request({
|
|
|
+ url: `${baseUrl}/my-resource/tag-ids/${resourceId}`,
|
|
|
+ method: 'GET'
|
|
|
+ })
|
|
|
+
|
|
|
+ if (!tagError && tagRes.statusCode === 200 && tagRes.data && tagRes.data.code === 200) {
|
|
|
+ tagIds = tagRes.data.data || []
|
|
|
+ console.log('根据resourceId获取的标签ID:', tagIds)
|
|
|
+ }
|
|
|
+ } catch (e) {
|
|
|
+ console.warn('根据resourceId获取标签ID失败,将使用标签名称查询:', e)
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ // 方法2: 如果方法1失败或没有resourceId,根据标签名称查询标签ID
|
|
|
+ if (tagIds.length === 0 && resource.tags && resource.tags.length > 0) {
|
|
|
+ try {
|
|
|
+ // 获取所有标签列表
|
|
|
+ const [tagListError, tagListRes] = await uni.request({
|
|
|
+ url: `${baseUrl}/tag/list`,
|
|
|
+ method: 'GET'
|
|
|
+ })
|
|
|
+
|
|
|
+ if (!tagListError && tagListRes.statusCode === 200 && tagListRes.data && tagListRes.data.code === 200) {
|
|
|
+ const allTags = tagListRes.data.data || []
|
|
|
+ console.log('所有标签列表:', allTags)
|
|
|
+
|
|
|
+ // 根据标签名称匹配标签ID
|
|
|
+ for (const tagName of resource.tags) {
|
|
|
+ const matchedTag = allTags.find(tag => {
|
|
|
+ const tagNameField = tag.name || tag.tag_name || tag.tagName
|
|
|
+ return tagNameField === tagName
|
|
|
+ })
|
|
|
+
|
|
|
+ if (matchedTag) {
|
|
|
+ const tagId = matchedTag.id || matchedTag.tag_id
|
|
|
+ if (tagId && !tagIds.includes(tagId)) {
|
|
|
+ tagIds.push(tagId)
|
|
|
+ console.log(`找到标签 "${tagName}" 的ID:`, tagId)
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ console.warn(`未找到标签 "${tagName}" 的ID`)
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ console.log('根据标签名称查询到的标签ID列表:', tagIds)
|
|
|
+ }
|
|
|
+ } catch (e) {
|
|
|
+ console.error('根据标签名称查询标签ID异常:', e)
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ // 确保tagIds是整数数组
|
|
|
+ tagIds = tagIds.map(id => parseInt(id)).filter(id => !isNaN(id) && id > 0)
|
|
|
+
|
|
|
+ if (tagIds.length === 0) {
|
|
|
+ console.warn('⚠️ 未获取到任何标签ID,资源将不包含标签')
|
|
|
+ } else {
|
|
|
+ console.log('✅ 最终获取到的标签ID列表:', tagIds)
|
|
|
+ }
|
|
|
+
|
|
|
+ // 调用后端API添加资源
|
|
|
+ const url = `${baseUrl}/my-resource/add?currentUserId=${this.currentUserId}`
|
|
|
+ console.log('添加资源请求URL:', url)
|
|
|
+ console.log('添加资源数据:', JSON.stringify(resourceData, null, 2))
|
|
|
+ console.log('标签ID列表:', tagIds)
|
|
|
+
|
|
|
+ const [error, res] = await uni.request({
|
|
|
+ url: url,
|
|
|
+ method: 'POST',
|
|
|
+ data: {
|
|
|
+ ...resourceData,
|
|
|
+ tagIds: tagIds
|
|
|
+ },
|
|
|
+ header: {
|
|
|
+ 'Content-Type': 'application/json'
|
|
|
+ }
|
|
|
+ })
|
|
|
+
|
|
|
+ uni.hideLoading()
|
|
|
+
|
|
|
+ if (error) {
|
|
|
+ console.error('添加到我的资源失败:', error)
|
|
|
+ uni.showToast({
|
|
|
+ title: '添加失败,请重试',
|
|
|
+ icon: 'none'
|
|
|
+ })
|
|
|
+ return
|
|
|
+ }
|
|
|
+
|
|
|
+ if (res.statusCode === 200 && res.data && res.data.code === 200) {
|
|
|
+ uni.showToast({
|
|
|
+ title: '添加成功',
|
|
|
+ icon: 'success'
|
|
|
+ })
|
|
|
+
|
|
|
+ // 发送刷新事件,通知我的资源页面刷新列表
|
|
|
+ uni.$emit('refreshResourceList')
|
|
|
+ } else {
|
|
|
+ console.error('添加到我的资源失败:', res.data.message)
|
|
|
+ uni.showToast({
|
|
|
+ title: res.data.message || '添加失败',
|
|
|
+ icon: 'none',
|
|
|
+ duration: 2000
|
|
|
+ })
|
|
|
+ }
|
|
|
+ } catch (e) {
|
|
|
+ uni.hideLoading()
|
|
|
+ console.error('添加到我的资源异常:', e)
|
|
|
+ uni.showToast({
|
|
|
+ title: '添加异常,请稍后重试',
|
|
|
+ icon: 'none'
|
|
|
+ })
|
|
|
+ }
|
|
|
+ },
|
|
|
+ // 获取头像URL(支持驼峰和下划线格式)
|
|
|
+ getAvatarUrl(resource) {
|
|
|
+ if (!resource) return ''
|
|
|
+ // 优先使用 avatarUrl(驼峰),如果没有则使用 avatar_url(下划线),最后使用 avatar
|
|
|
+ return resource.avatarUrl || resource.avatar_url || resource.avatar || ''
|
|
|
+ },
|
|
|
+ // 获取匹配状态(支持驼峰和下划线格式)
|
|
|
+ getIsMatch(resource) {
|
|
|
+ if (!resource) return 0
|
|
|
+ // 支持 isMatch(驼峰)和 is_match(下划线)两种格式
|
|
|
+ return resource.isMatch !== undefined ? resource.isMatch :
|
|
|
+ (resource.is_match !== undefined ? resource.is_match : 0)
|
|
|
+ },
|
|
|
+ // 获取择偶要求(支持驼峰和下划线格式)
|
|
|
+ getMateSelectionCriteria(resource) {
|
|
|
+ if (!resource) {
|
|
|
+ console.warn('getMateSelectionCriteria: resource为空')
|
|
|
+ return ''
|
|
|
+ }
|
|
|
+
|
|
|
+ // 支持 mateSelectionCriteria(驼峰)和 mate_selection_criteria(下划线)两种格式
|
|
|
+ let criteria = resource.mateSelectionCriteria || resource.mate_selection_criteria || ''
|
|
|
+
|
|
|
+ // 如果为空,直接返回
|
|
|
+ if (!criteria || criteria.trim() === '') {
|
|
|
+ return ''
|
|
|
+ }
|
|
|
+
|
|
|
+ // 去除首尾空格
|
|
|
+ criteria = criteria.trim()
|
|
|
+
|
|
|
+ // 如果获取到的是电话号码格式(11位数字或脱敏后的格式),则返回空字符串,让模板显示"暂无"
|
|
|
+ // 检查是否是纯数字(11位)或包含****的脱敏格式
|
|
|
+ const phonePattern = /^(\d{3}\*{4}\d{4}|\d{11})$/
|
|
|
+ if (phonePattern.test(criteria)) {
|
|
|
+ console.warn('⚠️ 择偶要求字段包含电话号码格式,返回空字符串', {
|
|
|
+ criteria: criteria,
|
|
|
+ phone: resource.phone,
|
|
|
+ 'resource完整对象': resource
|
|
|
+ })
|
|
|
+ return ''
|
|
|
+ }
|
|
|
+
|
|
|
+ // 如果择偶要求等于电话号码(未脱敏),也返回空
|
|
|
+ if (criteria === resource.phone || criteria === (resource.phone || '').replace(/(\d{3})\d{4}(\d{4})/, '$1****$2')) {
|
|
|
+ console.warn('⚠️ 择偶要求等于电话号码,返回空字符串', {
|
|
|
+ criteria: criteria,
|
|
|
+ phone: resource.phone
|
|
|
+ })
|
|
|
+ return ''
|
|
|
+ }
|
|
|
+
|
|
|
+ return criteria
|
|
|
+ },
|
|
|
+ // 获取脱敏手机号
|
|
|
+ getMaskedPhone(phone) {
|
|
|
+ if (!phone) return ''
|
|
|
+ // 手机号脱敏:显示前3位和后4位,中间用****代替
|
|
|
+ return phone.replace(/(\d{3})\d{4}(\d{4})/, '$1****$2')
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
@@ -215,6 +763,7 @@ export default {
|
|
|
border-radius: 50%;
|
|
|
background: #F0F0F0;
|
|
|
margin-right: 20rpx;
|
|
|
+ flex-shrink: 0;
|
|
|
}
|
|
|
|
|
|
.resource-info {
|
|
|
@@ -239,87 +788,169 @@ export default {
|
|
|
background: #F5F5F5;
|
|
|
border-radius: 12rpx;
|
|
|
}
|
|
|
-
|
|
|
- .status {
|
|
|
- font-size: 24rpx;
|
|
|
- color: #FF6B8A;
|
|
|
- padding: 4rpx 12rpx;
|
|
|
- background: #FFF3F5;
|
|
|
- border-radius: 12rpx;
|
|
|
- }
|
|
|
}
|
|
|
|
|
|
- .tags {
|
|
|
- display: flex;
|
|
|
- flex-wrap: wrap;
|
|
|
- gap: 10rpx;
|
|
|
+ .status-tag-wrapper {
|
|
|
+ display: flex;
|
|
|
+ align-items: center;
|
|
|
+ gap: 10rpx;
|
|
|
+ margin-bottom: 10rpx;
|
|
|
|
|
|
- .tag {
|
|
|
+ .status-tag {
|
|
|
font-size: 22rpx;
|
|
|
- color: #9C27B0;
|
|
|
padding: 6rpx 14rpx;
|
|
|
- background: #F3E5F5;
|
|
|
- border-radius: 14rpx;
|
|
|
+ border-radius: 12rpx;
|
|
|
+ font-weight: 500;
|
|
|
+
|
|
|
+ &.register-tag {
|
|
|
+ &.registered {
|
|
|
+ color: #4CAF50;
|
|
|
+ background: #E8F5E9;
|
|
|
+ border: 1rpx solid #C8E6C9;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ &.match-tag {
|
|
|
+ &.matched {
|
|
|
+ color: #2196F3;
|
|
|
+ background: #E3F2FD;
|
|
|
+ border: 1rpx solid #BBDEFB;
|
|
|
+ }
|
|
|
+
|
|
|
+ &.unmatched {
|
|
|
+ color: #FF9800;
|
|
|
+ background: #FFF3E0;
|
|
|
+ border: 1rpx solid #FFE0B2;
|
|
|
+ }
|
|
|
+ }
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
|
|
|
.resource-details {
|
|
|
-
|
|
|
- .requirement {
|
|
|
+ .labels {
|
|
|
display: flex;
|
|
|
+ flex-wrap: wrap;
|
|
|
+ gap: 10rpx;
|
|
|
margin-bottom: 15rpx;
|
|
|
|
|
|
+ .label {
|
|
|
+ display: inline-block;
|
|
|
+ padding: 6rpx 14rpx;
|
|
|
+ background: #F3E5F5;
|
|
|
+ color: #9C27B0;
|
|
|
+ border-radius: 15rpx;
|
|
|
+ font-size: 22rpx;
|
|
|
+ font-weight: 500;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ .requirement-box {
|
|
|
+ background: #F3E5F5;
|
|
|
+ border-radius: 12rpx;
|
|
|
+ padding: 16rpx 20rpx;
|
|
|
+ margin-bottom: 15rpx;
|
|
|
+ display: flex;
|
|
|
+ align-items: center;
|
|
|
+ flex-wrap: wrap;
|
|
|
+
|
|
|
.requirement-label {
|
|
|
- font-size: 26rpx;
|
|
|
- color: #666;
|
|
|
- margin-right: 10rpx;
|
|
|
+ font-size: 28rpx;
|
|
|
+ color: #7B1FA2;
|
|
|
+ font-weight: 500;
|
|
|
+ margin-right: 8rpx;
|
|
|
+ white-space: nowrap;
|
|
|
}
|
|
|
|
|
|
.requirement-content {
|
|
|
- font-size: 26rpx;
|
|
|
- color: #333;
|
|
|
+ font-size: 28rpx;
|
|
|
+ color: #7B1FA2;
|
|
|
+ font-weight: 400;
|
|
|
}
|
|
|
}
|
|
|
|
|
|
- .contact-info {
|
|
|
+ .contact-box {
|
|
|
+ margin-bottom: 20rpx;
|
|
|
display: flex;
|
|
|
align-items: center;
|
|
|
- margin-bottom: 20rpx;
|
|
|
+ flex-wrap: wrap;
|
|
|
|
|
|
.contact-label {
|
|
|
font-size: 26rpx;
|
|
|
- color: #666;
|
|
|
+ color: #333;
|
|
|
+ font-weight: 500;
|
|
|
margin-right: 10rpx;
|
|
|
+ white-space: nowrap;
|
|
|
}
|
|
|
|
|
|
.contact-number {
|
|
|
+ flex: 1;
|
|
|
font-size: 26rpx;
|
|
|
color: #333;
|
|
|
- margin-right: 15rpx;
|
|
|
+ font-weight: 400;
|
|
|
+ min-width: 0;
|
|
|
}
|
|
|
|
|
|
.copy-btn {
|
|
|
font-size: 24rpx;
|
|
|
color: #9C27B0;
|
|
|
- padding: 6rpx 16rpx;
|
|
|
- background: #F3E5F5;
|
|
|
- border-radius: 14rpx;
|
|
|
+ font-weight: 500;
|
|
|
+ margin-left: 15rpx;
|
|
|
+ white-space: nowrap;
|
|
|
+ cursor: pointer;
|
|
|
}
|
|
|
}
|
|
|
|
|
|
- .action-btn {
|
|
|
- width: 200rpx;
|
|
|
- height: 60rpx;
|
|
|
+ .action-buttons {
|
|
|
display: flex;
|
|
|
+ justify-content: flex-end;
|
|
|
align-items: center;
|
|
|
- justify-content: center;
|
|
|
- background: #9C27B0;
|
|
|
- color: #FFFFFF;
|
|
|
- font-size: 28rpx;
|
|
|
- border-radius: 30rpx;
|
|
|
- margin-left: auto;
|
|
|
+ gap: 15rpx;
|
|
|
+
|
|
|
+ .action-btn {
|
|
|
+ padding: 14rpx 30rpx;
|
|
|
+ border-radius: 25rpx;
|
|
|
+ font-size: 26rpx;
|
|
|
+ font-weight: 500;
|
|
|
+ text-align: center;
|
|
|
+
|
|
|
+ &.add-resource-btn {
|
|
|
+ background: #FF9800;
|
|
|
+ color: #FFFFFF;
|
|
|
+ }
|
|
|
+
|
|
|
+ &.chat-btn {
|
|
|
+ background: linear-gradient(135deg, #9C27B0 0%, #BA68C8 100%);
|
|
|
+ color: #FFFFFF;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+.loading-wrapper,
|
|
|
+.empty-wrapper,
|
|
|
+.load-more-wrapper,
|
|
|
+.no-more-wrapper {
|
|
|
+ display: flex;
|
|
|
+ justify-content: center;
|
|
|
+ align-items: center;
|
|
|
+ padding: 40rpx 0;
|
|
|
+
|
|
|
+ .loading-text,
|
|
|
+ .empty-text,
|
|
|
+ .load-more-text,
|
|
|
+ .no-more-text {
|
|
|
+ font-size: 26rpx;
|
|
|
+ color: #999;
|
|
|
}
|
|
|
}
|
|
|
+
|
|
|
+.empty-text {
|
|
|
+ color: #666;
|
|
|
+}
|
|
|
+
|
|
|
+.no-more-text {
|
|
|
+ color: #999;
|
|
|
+}
|
|
|
</style>
|