Selaa lähdekoodia

上线测试更改BUG

wangwenju 7 tuntia sitten
vanhempi
commit
feb815bf16

+ 150 - 12
LiangZhiYUMao/pages/matchmaker-workbench/client-detail.vue

@@ -271,28 +271,31 @@ export default {
 		}
 	},
 	onLoad(options) {
-		
-		// 从URL参数获取资源ID
+		// 从URL参数获取资源ID或用户ID
 		let resourceId = null
+		let userId = null
+		
 		if (options.resourceId) {
 			resourceId = options.resourceId
-			
 		} else if (options.id) {
 			// 兼容旧的id参数
 			resourceId = options.id
-			
+		}
+		
+		// 检查是否有userId参数(从优质资源列表进入时使用)
+		if (options.userId) {
+			userId = options.userId
 		}
 		
 		// 检查是否从优质资源列表进入
 		if (options.fromQualityResources === '1' || options.fromQualityResources === 1) {
 			this.fromQualityResources = true
-			
 		}
 		
 		// 获取当前登录用户的ID
-		const userId = uni.getStorageSync('userId')
-		if (userId) {
-			const rawUserId = parseInt(userId)
+		const currentUserId = uni.getStorageSync('userId')
+		if (currentUserId) {
+			const rawUserId = parseInt(currentUserId)
 			if (!isNaN(rawUserId) && rawUserId > 0) {
 				this.currentUserId = rawUserId
 				
@@ -301,11 +304,23 @@ export default {
 			}
 		}
 		
-		if (resourceId) {
+		// 优先使用userId(从优质资源列表进入)
+		if (userId) {
+			userId = parseInt(userId)
+			if (isNaN(userId) || userId <= 0) {
+				uni.showToast({
+					title: '用户ID无效',
+					icon: 'none'
+				})
+				return
+			}
+			
+			// 使用userId加载用户详情
+			this.loadUserInfo(userId)
+		} else if (resourceId) {
 			// 确保resourceId是数字类型
 			resourceId = parseInt(resourceId)
 			if (isNaN(resourceId) || resourceId <= 0) {
-				
 				uni.showToast({
 					title: '资源ID无效',
 					icon: 'none'
@@ -316,9 +331,8 @@ export default {
 			this.resourceId = resourceId
 			this.loadClientInfo(resourceId)
 		} else {
-			
 			uni.showToast({
-				title: '未获取到资源ID',
+				title: '未获取到资源ID或用户ID',
 				icon: 'none'
 			})
 		}
@@ -845,6 +859,130 @@ export default {
 				})
 			}
 		},
+		// 从API加载用户信息(用于优质资源列表点击查看详情)
+		async loadUserInfo(userId) {
+			try {
+				uni.showLoading({
+					title: '加载中...'
+				})
+				
+				const baseUrl = process.env.NODE_ENV === 'development' 
+					? 'https://api.zhongruanke.cn/api'
+					: 'https://api.zhongruanke.cn/api'
+				
+				const requestUrl = `${baseUrl}/my-resource/user-detail/${userId}`
+				
+				const [error, res] = await uni.request({
+					url: requestUrl,
+					method: 'GET',
+					timeout: 30000,
+					header: {
+						'Content-Type': 'application/json'
+					}
+				})
+				
+				uni.hideLoading()
+				
+				if (error) {
+					let errorMsg = '加载失败'
+					if (error.errMsg) {
+						if (error.errMsg.includes('timeout') || error.errMsg.includes('超时')) {
+							errorMsg = '请求超时,请检查网络连接'
+						} else if (error.errMsg.includes('fail')) {
+							errorMsg = '网络连接失败'
+						}
+					}
+					uni.showToast({
+						title: errorMsg,
+						icon: 'none',
+						duration: 3000
+					})
+					return
+				}
+				
+				if (res.statusCode === 200 && res.data && res.data.code === 200) {
+					const data = res.data.data
+					
+					// 支持驼峰和下划线两种字段名格式
+					const avatarUrl = data.avatarUrl || data.avatar_url
+					
+					// 择偶要求详情字段
+					const minAge = data.minAge !== undefined ? data.minAge : data.min_age
+					const maxAge = data.maxAge !== undefined ? data.maxAge : data.max_age
+					const minHeight = data.minHeight !== undefined ? data.minHeight : data.min_height
+					const maxHeight = data.maxHeight !== undefined ? data.maxHeight : data.max_height
+					const educationLevel = data.educationLevel !== undefined ? data.educationLevel : data.education_level
+					const salaryRange = data.salaryRange !== undefined ? data.salaryRange : data.salary_range
+					const houseRequirement = data.houseRequirement !== undefined ? data.houseRequirement : data.house_requirement
+					const carRequirement = data.carRequirement !== undefined ? data.carRequirement : data.car_requirement
+					const maritalStatusRequirement = data.maritalStatusRequirement !== undefined ? data.maritalStatusRequirement : data.marital_status_requirement
+					const preferredCity = data.preferredCity || data.preferred_city
+					const otherRequirements = data.otherRequirements || data.other_requirements
+					
+					// 处理标签列表
+					let clientTags = []
+					if (data.tags && Array.isArray(data.tags) && data.tags.length > 0) {
+						clientTags = data.tags
+					} else {
+						if (data.constellation) {
+							clientTags.push(data.constellation)
+						}
+						if (data.occupation) {
+							clientTags.push(data.occupation)
+						}
+					}
+					
+					// 从优质资源进入,不能跟进(因为还没有添加到我的资源)
+					this.canFollow = false
+					
+					// 映射数据到clientInfo
+					this.clientInfo = {
+						id: userId,
+						name: data.name || data.nickname || '',
+						gender: data.gender === 1 ? '男' : data.gender === 2 ? '女' : '未知',
+						status: '未绑定',
+						tags: clientTags,
+						avatar: avatarUrl || '',
+						requirement: '暂无要求',
+						contact: data.phone ? data.phone.replace(/(\d{3})\d{4}(\d{4})/, '$1****$2') : '',
+						backupContact: '',
+						originalPhone: data.phone || '',
+						originalBackupPhone: '',
+						stats: {
+							followTimes: 0,
+							matchCount: 0,
+							phoneCalls: 0,
+							interviews: 0
+						},
+						details: {
+							maritalStatus: this.formatMaritalStatus(data.marrStatus || data.marr_status),
+							education: data.diploma || '未知',
+							occupation: data.occupation || '未知',
+							income: data.income || '未知',
+							housing: data.house === 1 ? '已购房' : data.house === 0 ? '未购房' : '未知',
+							requirement: {
+								ageRange: minAge && maxAge ? `${minAge}-${maxAge}岁` : '不限',
+								height: minHeight ? `${minHeight}cm以上` : '不限',
+								maritalStatus: this.formatMaritalStatusRequirement(maritalStatusRequirement),
+								education: this.formatEducationLevel(educationLevel),
+								other: otherRequirements || ''
+							}
+						}
+					}
+				} else {
+					uni.showToast({
+						title: res.data.message || '加载失败',
+						icon: 'none'
+					})
+				}
+			} catch (e) {
+				uni.hideLoading()
+				uni.showToast({
+					title: '加载失败',
+					icon: 'none'
+				})
+			}
+		},
 		// 格式化婚姻状况
 		formatMaritalStatus(status) {
 			if (status === null || status === undefined) return '未知'

+ 74 - 18
LiangZhiYUMao/pages/matchmaker-workbench/my-resources.vue

@@ -1,5 +1,8 @@
 <template>
+
+
 	<view class="my-resources">
+		
 		<view class="status-bar-placeholder" :style="{height: statusBarHeight + 'px', backgroundColor: '#FFFFFF'}"></view>
 		<!-- 顶部导航栏 -->
 		<view class="header">
@@ -20,18 +23,18 @@
 			</view>
 		</view>
 
-	<!-- 资源/线索切换标签 -->
-	<view class="tab-switcher">
-		<view class="tab-item" :class="{ active: currentTab === 'resource' }" @click="switchToResource">
-			<text class="tab-text">资源</text>
-			<text class="tab-count">({{ registeredTotal }})</text>
-		</view>
-		<view class="tab-item" :class="{ active: currentTab === 'clue' }" @click="switchToClue">
-			<text class="tab-text">线索</text>
-			<text class="tab-count">({{ unregisteredTotal }})</text>
+		<!-- 资源/线索切换标签 -->
+		<view class="tab-switcher">
+			<view class="tab-item" :class="{ active: currentTab === 'resource' }" @click="switchToResource">
+				<text class="tab-text">资源</text>
+				<text class="tab-count">({{ registeredTotal }})</text>
+			</view>
+			<view class="tab-item" :class="{ active: currentTab === 'clue' }" @click="switchToClue">
+				<text class="tab-text">线索</text>
+				<text class="tab-count">({{ unregisteredTotal }})</text>
+			</view>
 		</view>
-	</view>
-
+	
 	<scroll-view scroll-y class="content" @scrolltolower="handleScrollToLower" :lower-threshold="50" :enable-back-to-top="true" :scroll-with-animation="true">
 		<!-- 资源部分(已注册用户) -->
 		<view class="resource-section" v-if="currentTab === 'resource'">
@@ -431,6 +434,11 @@ export default {
 					const userId = uni.getStorageSync('userId')
 					let currentUserId = userInfo.userId || userId || null
 					
+					console.log('=== loadRegisteredPage 调试信息 ===')
+					console.log('userInfo:', JSON.stringify(userInfo))
+					console.log('userId from storage:', userId)
+					console.log('currentUserId:', currentUserId)
+					
 					if (currentUserId !== null && currentUserId !== undefined) {
 						currentUserId = parseInt(currentUserId)
 						if (isNaN(currentUserId) || currentUserId <= 0) {
@@ -439,7 +447,11 @@ export default {
 					}
 					
 					if (!currentUserId) {
-				
+						console.log('❌ 未获取到有效的用户ID,无法加载资源')
+						uni.showToast({
+							title: '请先登录',
+							icon: 'none'
+						})
 						this.registeredResources = []
 						this.registeredLoading = false
 						return
@@ -453,13 +465,24 @@ export default {
 						url += `&keyword=${encodeURIComponent(this.searchKeyword.trim())}`
 					}
 					
+					console.log('请求URL:', url)
+					
 					const [error, res] = await uni.request({
 						url: url,
-						method: 'GET'
+						method: 'GET',
+						timeout: 15000
 					})
 					
+					console.log('请求结果 - error:', error)
+					console.log('请求结果 - res.statusCode:', res ? res.statusCode : 'null')
+					console.log('请求结果 - res.data:', res ? JSON.stringify(res.data) : 'null')
+					
 					if (error) {
-						
+						console.log('❌ 请求失败:', JSON.stringify(error))
+						uni.showToast({
+							title: '网络请求失败',
+							icon: 'none'
+						})
 						this.registeredResources = []
 						this.registeredLoading = false
 						return
@@ -467,9 +490,12 @@ export default {
 					
 					if (res.statusCode === 200 && res.data && res.data.code === 200) {
 						const pageData = res.data.data
+						console.log('pageData:', JSON.stringify(pageData))
 						if (pageData && pageData.records) {
+							console.log('records数量:', pageData.records.length)
 							// 转换数据格式,并过滤掉无效数据(null值)
 							const resources = this.convertResourceData(pageData.records).filter(item => item !== null && item !== undefined)
+							console.log('转换后资源数量:', resources.length)
 							
 							// 如果是第一页,直接替换;否则追加
 							if (pageNum === 1) {
@@ -480,19 +506,24 @@ export default {
 							
 							// 更新总数(使用后端返回的total)
 							this.registeredTotal = pageData.total || 0
-							
+							console.log('资源总数:', this.registeredTotal)
 							
 						} else {
+							console.log('⚠️ pageData或records为空')
 							if (pageNum === 1) {
 								this.registeredResources = []
 								this.registeredTotal = 0
 							}
 						}
 					} else {
-						
+						console.log('❌ 响应状态异常:', res.statusCode, res.data)
+						uni.showToast({
+							title: res.data?.message || '加载失败',
+							icon: 'none'
+						})
 					}
 				} catch (e) {
-					
+					console.log('❌ 加载资源异常:', e)
 					if (this.registeredPageNum === 1) {
 						this.registeredResources = []
 					}
@@ -515,6 +546,11 @@ export default {
 					const userId = uni.getStorageSync('userId')
 					let currentUserId = userInfo.userId || userId || null
 					
+					console.log('=== loadUnregisteredPage 调试信息 ===')
+					console.log('userInfo:', JSON.stringify(userInfo))
+					console.log('userId from storage:', userId)
+					console.log('currentUserId:', currentUserId)
+					
 					if (currentUserId !== null && currentUserId !== undefined) {
 						currentUserId = parseInt(currentUserId)
 						if (isNaN(currentUserId) || currentUserId <= 0) {
@@ -523,6 +559,7 @@ export default {
 					}
 					
 					if (!currentUserId) {
+						console.log('❌ 未获取到有效的用户ID,无法加载线索')
 						this.unregisteredResources = []
 						this.unregisteredLoading = false
 						return
@@ -536,12 +573,23 @@ export default {
 						url += `&keyword=${encodeURIComponent(this.searchKeyword.trim())}`
 					}
 					
+					console.log('请求URL:', url)
+					
 					const [error, res] = await uni.request({
 						url: url,
-						method: 'GET'
+						method: 'GET',
+						timeout: 15000
 					})
 					
+					console.log('请求结果 - error:', error)
+					console.log('请求结果 - res.statusCode:', res ? res.statusCode : 'null')
+					
 					if (error) {
+						console.log('❌ 请求失败:', JSON.stringify(error))
+						uni.showToast({
+							title: '网络请求失败',
+							icon: 'none'
+						})
 						this.unregisteredResources = []
 						this.unregisteredLoading = false
 						return
@@ -549,10 +597,13 @@ export default {
 					
 					if (res.statusCode === 200 && res.data && res.data.code === 200) {
 						const pageData = res.data.data
+						console.log('pageData:', JSON.stringify(pageData))
 						
 						if (pageData && pageData.records) {
+							console.log('records数量:', pageData.records.length)
 							// 转换数据格式,并过滤掉无效数据(null值)
 							const resources = this.convertResourceData(pageData.records).filter(item => item !== null && item !== undefined)
+							console.log('转换后线索数量:', resources.length)
 							
 							// 如果是第一页,直接替换;否则追加
 							if (pageNum === 1) {
@@ -563,15 +614,20 @@ export default {
 							
 							// 更新总数(使用后端返回的total)
 							this.unregisteredTotal = pageData.total || 0
+							console.log('线索总数:', this.unregisteredTotal)
 							
 						} else {
+							console.log('⚠️ pageData或records为空')
 							if (pageNum === 1) {
 								this.unregisteredResources = []
 								this.unregisteredTotal = 0
 							}
 						}
+					} else {
+						console.log('❌ 响应状态异常:', res.statusCode, res.data)
 					}
 				} catch (e) {
+					console.log('❌ 加载线索异常:', e)
 					if (this.unregisteredPageNum === 1) {
 						this.unregisteredResources = []
 					}

+ 17 - 38
LiangZhiYUMao/pages/matchmaker-workbench/quality-resources.vue

@@ -324,11 +324,8 @@ export default {
 		},
 		// 点击资源项
 		handleResourceClick(index) {
-			
-			
 			// 检查index是否有效
 			if (index === undefined || index === null || index < 0 || index >= this.resources.length) {
-			
 				uni.showToast({
 					title: '资源索引无效',
 					icon: 'none'
@@ -339,9 +336,7 @@ export default {
 			// 从数组中获取resource对象
 			const resource = this.resources[index]
 			
-			
 			if (!resource) {
-				
 				uni.showToast({
 					title: '资源信息为空',
 					icon: 'none'
@@ -349,47 +344,31 @@ export default {
 				return
 			}
 			
+			// 优质资源返回的是用户信息,resource_id实际上是user_id
 			// 支持下划线和驼峰两种格式
-			const resourceId = resource.resourceId || resource.resource_id
-			const isUser = resource.isUser !== undefined ? resource.isUser : 
-			              (resource.is_user !== undefined ? resource.is_user : 0)
+			const userId = resource.userId || resource.user_id || resource.resourceId || resource.resource_id
 			
-			
-			
-			// 检查resourceId是否有效
-			if (!resourceId || resourceId === null || resourceId === undefined || resourceId === '') {
-				
+			// 检查userId是否有效
+			if (!userId || userId === null || userId === undefined || userId === '') {
 				uni.showToast({
-					title: '资源ID无效,无法查看详情',
+					title: '用户ID无效,无法查看详情',
 					icon: 'none'
 				})
 				return
 			}
 			
-			// 判断是否为已注册用户
-			if (isUser === 1 || isUser === '1') {
-				
-				uni.navigateTo({
-					url: `/pages/matchmaker-workbench/client-detail?resourceId=${resourceId}&fromQualityResources=1`,
-					success: () => {
-					
-					},
-					fail: (err) => {
-					
-						uni.showToast({
-							title: '跳转失败,请重试',
-							icon: 'none'
-						})
-					}
-				})
-			} else {
-				// 未注册,提示用户(虽然后端已经过滤了,但为了容错仍然保留)
-				uni.showToast({
-					title: '该用户还未注册用户端',
-					icon: 'none',
-					duration: 2000
-				})
-			}
+			// 跳转到用户详情页面,使用userId参数
+			uni.navigateTo({
+				url: `/pages/matchmaker-workbench/client-detail?userId=${userId}&fromQualityResources=1`,
+				success: () => {
+				},
+				fail: (err) => {
+					uni.showToast({
+						title: '跳转失败,请重试',
+						icon: 'none'
+					})
+				}
+			})
 		},
 		// 添加到我的资源
 		async handleAddToMyResources(index) {

+ 42 - 9
LiangZhiYUMao/pages/mine/index.vue

@@ -261,6 +261,7 @@
 
 <script>
 import api from '@/utils/api.js'
+import userStatusCheck from '@/utils/userStatusCheck.js'
 
 export default {
   data() {
@@ -788,7 +789,11 @@ export default {
       return `${year}-${month}-${day}`
     },
     // 显示签到弹窗
-    showCheckinPopup() {
+    async showCheckinPopup() {
+      // 检查用户是否被禁用
+      const canOperate = await userStatusCheck.checkAndTip()
+      if (!canOperate) return
+      
       this.$refs.checkinPopup.open()
     },
     // 关闭签到弹窗
@@ -848,21 +853,37 @@ export default {
         })
       }
     },
-    goVerify() {
+    async goVerify() {
+      // 检查用户是否被禁用
+      const canOperate = await userStatusCheck.checkAndTip()
+      if (!canOperate) return
+      
       uni.navigateTo({
         url: '/pages/settings/id-verification'
       })
     },
-    goCompleteProfile() {
+    async goCompleteProfile() {
+      // 检查用户是否被禁用
+      const canOperate = await userStatusCheck.checkAndTip()
+      if (!canOperate) return
+      
       this.goToPage('basicInfo')
     },
-    goVip() {
+    async goVip() {
+      // 检查用户是否被禁用
+      const canOperate = await userStatusCheck.checkAndTip()
+      if (!canOperate) return
+      
       uni.navigateTo({
         url: '/pages/vip/index'
       })
     },
-    goToPage(page) {
-     
+    async goToPage(page) {
+      // 设置页面不需要检查用户状态
+      if (page !== 'settings') {
+        const canOperate = await userStatusCheck.checkAndTip()
+        if (!canOperate) return
+      }
 
       try {
         if (page === 'basicInfo') {
@@ -1230,7 +1251,11 @@ export default {
     },
     
     // 统计数据板块点击事件
-    goToLikedByMe() {
+    async goToLikedByMe() {
+      // 检查用户是否被禁用
+      const canOperate = await userStatusCheck.checkAndTip()
+      if (!canOperate) return
+      
       // 跳转到我喜欢的页面
       uni.navigateTo({
         url: '/pages/mine/liked-by-me',
@@ -1301,7 +1326,11 @@ export default {
       }
     },
     
-    goToLikedMe() {
+    async goToLikedMe() {
+      // 检查用户是否被禁用
+      const canOperate = await userStatusCheck.checkAndTip()
+      if (!canOperate) return
+      
       // 跳转到喜欢我的页面
       uni.navigateTo({
         url: '/pages/mine/liked-me',
@@ -1315,7 +1344,11 @@ export default {
       })
     },
     
-    goToVisitedByMe() {
+    async goToVisitedByMe() {
+      // 检查用户是否被禁用
+      const canOperate = await userStatusCheck.checkAndTip()
+      if (!canOperate) return
+      
       // 跳转到我浏览的页面
       uni.navigateTo({
         url: '/pages/mine/visited-by-me',

+ 23 - 2
LiangZhiYUMao/pages/plaza/detail.vue

@@ -228,6 +228,7 @@
 
 <script>
 import api from '@/utils/api.js'
+import userStatusCheck from '@/utils/userStatusCheck.js'
 
 export default {
 	data() {
@@ -411,6 +412,10 @@ export default {
 		
 		// 处理点赞
 		async handleLike() {
+			// 检查用户是否被禁用
+			const canOperate = await userStatusCheck.checkAndTip()
+			if (!canOperate) return
+			
 			if (!this.dynamic || this.isLiking) return
 			
 			try {
@@ -456,6 +461,10 @@ export default {
 		
 		// 处理收藏
 		async handleFavorite() {
+			// 检查用户是否被禁用
+			const canOperate = await userStatusCheck.checkAndTip()
+			if (!canOperate) return
+			
 			if (!this.dynamic || this.isFavoriting) return
 			
 			try {
@@ -503,7 +512,11 @@ export default {
 		},
 		
 		// 显示评论输入
-		showCommentInput() {
+		async showCommentInput() {
+			// 检查用户是否被禁用
+			const canOperate = await userStatusCheck.checkAndTip()
+			if (!canOperate) return
+			
 			this.showInput = true
 		},
 		
@@ -669,6 +682,10 @@ export default {
 
 		// 评论点赞/取消
 		async toggleCommentLike(comment) {
+			// 检查用户是否被禁用
+			const canOperate = await userStatusCheck.checkAndTip()
+			if (!canOperate) return
+			
 			try {
 				if (comment.isLiked) {
 					await api.dynamic.unlikeComment(comment.commentId)
@@ -685,7 +702,11 @@ export default {
 		},
 
 		// 打开回复框
-		openReply(comment) {
+		async openReply(comment) {
+			// 检查用户是否被禁用
+			const canOperate = await userStatusCheck.checkAndTip()
+			if (!canOperate) return
+			
 			this.replyingToComment = comment
 			this.showInput = true
 			this.scrollIntoView = ''

+ 15 - 2
LiangZhiYUMao/pages/plaza/index.vue

@@ -167,6 +167,7 @@
 
 <script>
 import api from '@/utils/api.js'
+import userStatusCheck from '@/utils/userStatusCheck.js'
 
 export default {
 	data() {
@@ -364,6 +365,10 @@ export default {
 		
 		// 处理点赞
 		async handleLike(item) {
+			// 检查用户是否被禁用
+			const canOperate = await userStatusCheck.checkAndTip()
+			if (!canOperate) return
+			
 			// 防止重复点击:如果正在处理该动态的点赞请求,直接返回
 			if (this.likingMap[item.dynamicId]) {
 				return
@@ -411,6 +416,10 @@ export default {
 		
 		// 处理收藏
 		async handleFavorite(item) {
+			// 检查用户是否被禁用
+			const canOperate = await userStatusCheck.checkAndTip()
+			if (!canOperate) return
+			
 			// 防止重复点击:如果正在处理该动态的收藏请求,直接返回
 			if (this.favoritingMap[item.dynamicId]) {
 				return
@@ -475,8 +484,12 @@ export default {
 		},
 		
 		// 跳转到发布页
-		goToPublish() {
-			 console.log('点击了发布按钮');
+		async goToPublish() {
+			// 检查用户是否被禁用
+			const canOperate = await userStatusCheck.checkAndTip()
+			if (!canOperate) return
+			
+			console.log('点击了发布按钮');
 			uni.navigateTo({
 				url: '/pages/plaza/publish',
 				   fail: (err) => {

+ 22 - 2
LiangZhiYUMao/pages/recommend/index.vue

@@ -251,6 +251,7 @@
 
 <script>
 import api from '@/utils/api.js'
+import userStatusCheck from '@/utils/userStatusCheck.js'
 import uniPopup from '@/uni_modules/uni-popup/components/uni-popup/uni-popup.vue'
 export default {
   components: { uniPopup },
@@ -551,9 +552,24 @@ export default {
 			
 			this.refresh(true);
 		},
-		openFilter(){ this.ensureAreaData(); this.$refs.filterPopup.open('bottom') },
+		openFilter(){ 
+			// 筛选功能需要检查用户状态
+			userStatusCheck.checkAndTip().then(canOperate => {
+				if (canOperate) {
+					this.ensureAreaData(); 
+					this.$refs.filterPopup.open('bottom')
+				}
+			})
+		},
 		closeFilter(){ this.$refs.filterPopup.close() },
-		applyFilter(){ 
+		async applyFilter(){ 
+			// 检查用户是否被禁用
+			const canOperate = await userStatusCheck.checkAndTip()
+			if (!canOperate) {
+				this.$refs.filterPopup.close()
+				return
+			}
+			
 			this.$refs.filterPopup.close(); 
 			// 应用筛选时,清空已显示列表,重新开始
 			this.shownUserIds = [];
@@ -744,6 +760,10 @@ export default {
 		fmtSalary(v){ const map={1:'<5k',2:'5-10k',3:'10-20k',4:'20-50k',5:'50k+'}; return map[v]||'-' },
 		parseHobby(h){ try{ const arr = typeof h === 'string' ? JSON.parse(h) : h; return Array.isArray(arr)?arr.slice(0,6):[] }catch{return []} },
 		async toggleLike(i){ 
+			// 检查用户是否被禁用
+			const canOperate = await userStatusCheck.checkAndTip()
+			if (!canOperate) return
+			
 			const u=this.list[i]; 
 			if(!u) return; 
 			const uid = parseInt(uni.getStorageSync('userId')||1); 

+ 123 - 0
LiangZhiYUMao/utils/userStatusCheck.js

@@ -0,0 +1,123 @@
+/**
+ * 用户状态检查工具类
+ * 用于检查用户是否被禁用,并在被禁用时显示提示
+ * 支持实时刷新状态,当后台修改用户状态后能及时响应
+ */
+
+const BASE_URL = 'https://api.zhongruanke.cn/api'
+
+export default {
+  /**
+   * 检查用户是否被禁用(每次操作都实时请求后端)
+   * @param {boolean} useCache - 是否使用缓存,默认false(实时请求)
+   * @returns {Promise<boolean>} true表示用户正常,false表示用户被禁用
+   */
+  async checkUserStatus(useCache = false) {
+    try {
+      const userId = uni.getStorageSync('userId')
+      if (!userId) {
+        return true // 未登录用户不检查
+      }
+      
+      // 如果允许使用缓存,检查缓存(缓存有效期30秒,用于短时间内连续操作)
+      if (useCache) {
+        const cachedStatus = uni.getStorageSync('userStatus')
+        const cacheTime = uni.getStorageSync('userStatusCacheTime')
+        const now = Date.now()
+        
+        // 缓存有效期30秒(短时间内连续操作不重复请求)
+        if (cachedStatus !== undefined && cacheTime && (now - cacheTime) < 30 * 1000) {
+          return cachedStatus !== 0
+        }
+      }
+      
+      // 调用后端接口获取用户状态(实时请求)
+      const [error, res] = await uni.request({
+        url: `${BASE_URL}/user/status/${userId}`,
+        method: 'GET',
+        timeout: 5000
+      })
+      
+      if (error) {
+        console.error('检查用户状态失败:', error)
+        return true // 网络错误时默认允许操作
+      }
+      
+      if (res.statusCode === 200 && res.data && res.data.code === 200) {
+        const status = res.data.data?.status
+        const now = Date.now()
+        
+        // 更新缓存
+        uni.setStorageSync('userStatus', status)
+        uni.setStorageSync('userStatusCacheTime', now)
+        
+        if (status === 0) {
+          return false // 用户被禁用
+        }
+      }
+      
+      return true
+    } catch (e) {
+      console.error('检查用户状态异常:', e)
+      return true // 异常时默认允许操作
+    }
+  },
+  
+  /**
+   * 显示用户被禁用的提示
+   */
+  showDisabledTip() {
+    uni.showModal({
+      title: '账号已被禁用',
+      content: '您的当前账号违反规定已被禁用,如有疑问请联系客服',
+      showCancel: false,
+      confirmText: '我知道了'
+    })
+  },
+  
+  /**
+   * 检查用户状态,如果被禁用则显示提示并返回false
+   * 每次调用都会实时请求后端,确保状态最新
+   * @returns {Promise<boolean>} true表示可以继续操作,false表示被禁用
+   */
+  async checkAndTip() {
+    // 实时请求后端,不使用缓存,确保状态最新
+    const isNormal = await this.checkUserStatus(false)
+    if (!isNormal) {
+      this.showDisabledTip()
+      return false
+    }
+    return true
+  },
+  
+  /**
+   * 带缓存的状态检查(用于短时间内连续操作,减少请求)
+   * 缓存有效期30秒
+   * @returns {Promise<boolean>} true表示可以继续操作,false表示被禁用
+   */
+  async checkAndTipWithCache() {
+    const isNormal = await this.checkUserStatus(true)
+    if (!isNormal) {
+      this.showDisabledTip()
+      return false
+    }
+    return true
+  },
+  
+  /**
+   * 清除用户状态缓存(用于登录/登出时)
+   */
+  clearStatusCache() {
+    uni.removeStorageSync('userStatus')
+    uni.removeStorageSync('userStatusCacheTime')
+  },
+  
+  /**
+   * 强制刷新用户状态(绕过缓存)
+   * @returns {Promise<boolean>} true表示用户正常,false表示用户被禁用
+   */
+  async refreshUserStatus() {
+    this.clearStatusCache()
+    return await this.checkUserStatus(false)
+  }
+}

+ 45 - 0
service/Essential/src/main/java/com/zhentao/controller/UserController.java

@@ -341,5 +341,50 @@ public class UserController {
             return Result.error("服务异常: " + e.getMessage());
         }
     }
+    
+    /**
+     * 获取用户状态(用于检查用户是否被禁用)
+     * @param userId 用户ID
+     * @return 用户状态信息 {status: 0-禁用, 1-正常}
+     */
+    @GetMapping("/status/{userId}")
+    public Result<java.util.Map<String, Object>> getUserStatus(@PathVariable Long userId) {
+        System.out.println("=== UserController.getUserStatus 接收请求 ===");
+        System.out.println("查询用户ID: " + userId);
+        
+        try {
+            if (userId == null || userId <= 0) {
+                System.out.println("❌ 用户ID无效: " + userId);
+                return Result.error("用户ID无效");
+            }
+            
+            // 查询用户信息
+            UserInfoVO userInfo = userService.getUserInfo(userId);
+            
+            if (userInfo == null) {
+                System.out.println("❌ 用户不存在: " + userId);
+                return Result.error("用户不存在");
+            }
+            
+            // 获取status字段值(0-禁用, 1-正常)
+            Integer status = userInfo.getStatus();
+            if (status == null) {
+                status = 1; // 默认值为1(正常)
+            }
+            
+            System.out.println("✅ 查询成功,用户: " + userInfo.getNickname() + ", status: " + status);
+            
+            // 构造返回数据
+            java.util.Map<String, Object> result = new java.util.HashMap<>();
+            result.put("userId", userId);
+            result.put("status", status);
+            
+            return Result.success(result);
+        } catch (Exception e) {
+            System.err.println("❌ 查询用户状态失败: " + e.getMessage());
+            e.printStackTrace();
+            return Result.error("查询用户状态失败: " + e.getMessage());
+        }
+    }
 }
 

+ 29 - 0
service/homePage/src/main/java/com/zhentao/controller/MyResourceController.java

@@ -359,6 +359,35 @@ public class MyResourceController {
         }
     }
     
+    /**
+     * 根据用户ID获取用户详情(用于优质资源列表点击查看详情)
+     * 
+     * @param userId 用户ID
+     * @return 用户详情
+     */
+    @GetMapping("/user-detail/{userId}")
+    public Result<ClientDetailVO> getUserDetail(@PathVariable Integer userId) {
+        try {
+            System.out.println("=== 获取用户详情 ===");
+            System.out.println("接收到的userId: " + userId);
+            
+            ClientDetailVO clientDetail = myResourceService.getUserDetailByUserId(userId);
+            if (clientDetail == null) {
+                System.out.println("用户不存在,userId: " + userId);
+                return Result.error("用户不存在");
+            }
+            
+            System.out.println("查询成功,返回的userId: " + clientDetail.getUserId());
+            System.out.println("姓名: " + clientDetail.getName());
+            System.out.println("头像URL: " + clientDetail.getAvatarUrl());
+            
+            return Result.success(clientDetail);
+        } catch (Exception e) {
+            e.printStackTrace();
+            return Result.error("查询用户详情失败:" + e.getMessage());
+        }
+    }
+    
     /**
      * 更新资源信息
      * 

+ 7 - 0
service/homePage/src/main/java/com/zhentao/service/MyResourceService.java

@@ -100,6 +100,13 @@ public interface MyResourceService extends IService<MyResource> {
      * @return 标签ID列表
      */
     List<Integer> getTagIdsByResourceId(Integer resourceId);
+    
+    /**
+     * 根据用户ID获取用户详情(用于优质资源列表点击查看详情)
+     * @param userId 用户ID
+     * @return 用户详情
+     */
+    com.zhentao.vo.ClientDetailVO getUserDetailByUserId(Integer userId);
 
     /**
      * 搜索资源(按姓名或手机号)

+ 98 - 0
service/homePage/src/main/java/com/zhentao/service/impl/MyResourceServiceImpl.java

@@ -406,6 +406,104 @@ public class MyResourceServiceImpl extends ServiceImpl<MyResourceMapper, MyResou
         return tagIds != null ? tagIds : new java.util.ArrayList<>();
     }
     
+    @Override
+    public ClientDetailVO getUserDetailByUserId(Integer userId) {
+        System.out.println("=== MyResourceService.getUserDetailByUserId ===");
+        System.out.println("查询userId: " + userId);
+        
+        if (userId == null) {
+            System.out.println("userId为空");
+            return null;
+        }
+        
+        // 根据userId查询users表
+        User user = userMapper.selectById(userId);
+        if (user == null) {
+            System.out.println("未找到用户,userId: " + userId);
+            return null;
+        }
+        
+        System.out.println("找到用户:");
+        System.out.println("  userId: " + user.getUserId());
+        System.out.println("  nickname: " + user.getNickname());
+        System.out.println("  phone: " + user.getPhone());
+        
+        // 创建ClientDetailVO并填充基本信息
+        ClientDetailVO clientDetail = new ClientDetailVO();
+        clientDetail.setUserId(user.getUserId());
+        clientDetail.setName(user.getNickname());
+        clientDetail.setGender(user.getGender());
+        clientDetail.setPhone(user.getPhone());
+        clientDetail.setAvatarUrl(user.getAvatarUrl());
+        
+        // 从user_profile表获取其他基本信息
+        java.util.Map<String, Object> profileMap = myResourceMapper.selectUserProfileByUserId(user.getUserId());
+        if (profileMap != null) {
+            // 年龄
+            Object birthDateObj = profileMap.get("birth_date");
+            if (birthDateObj != null) {
+                java.util.Date birthDate = null;
+                if (birthDateObj instanceof java.util.Date) {
+                    birthDate = (java.util.Date) birthDateObj;
+                } else if (birthDateObj instanceof java.sql.Date) {
+                    birthDate = new java.util.Date(((java.sql.Date) birthDateObj).getTime());
+                }
+                if (birthDate != null) {
+                    java.util.Calendar cal = java.util.Calendar.getInstance();
+                    java.util.Calendar birthCal = java.util.Calendar.getInstance();
+                    birthCal.setTime(birthDate);
+                    int age = cal.get(java.util.Calendar.YEAR) - birthCal.get(java.util.Calendar.YEAR);
+                    clientDetail.setAge(age);
+                }
+            }
+            // 身高
+            if (profileMap.get("height") != null) {
+                clientDetail.setHeight((Integer) profileMap.get("height"));
+            }
+            // 体重
+            if (profileMap.get("weight") != null) {
+                clientDetail.setWeight((Integer) profileMap.get("weight"));
+            }
+            // 星座
+            if (profileMap.get("constellation") != null) {
+                clientDetail.setConstellation((String) profileMap.get("constellation"));
+            }
+        }
+        
+        // 设置默认值
+        clientDetail.setIsMatch(0);
+        clientDetail.setIsInvitation(0);
+        clientDetail.setInvitationTime(null);
+        
+        // 根据user_id查询partner_requirement表获取择偶要求
+        if (partnerRequirementService != null) {
+            try {
+                System.out.println("  开始查询择偶要求,userId: " + userId);
+                PartnerRequirement requirement = partnerRequirementService.getByUserId(userId.longValue());
+                if (requirement != null) {
+                    System.out.println("  ✅ 查询到择偶要求");
+                    clientDetail.setMinAge(requirement.getMinAge());
+                    clientDetail.setMaxAge(requirement.getMaxAge());
+                    clientDetail.setMinHeight(requirement.getMinHeight());
+                    clientDetail.setMaxHeight(requirement.getMaxHeight());
+                    clientDetail.setEducationLevel(requirement.getEducationLevel());
+                    clientDetail.setSalaryRange(requirement.getSalaryRange());
+                    clientDetail.setHouseRequirement(requirement.getHouse());
+                    clientDetail.setCarRequirement(requirement.getCar());
+                    clientDetail.setMaritalStatusRequirement(requirement.getMaritalStatus());
+                    clientDetail.setPreferredCity(requirement.getPreferredCity());
+                    clientDetail.setOtherRequirements(requirement.getOtherRequirements());
+                } else {
+                    System.out.println("  ⚠️ 未找到择偶要求记录");
+                }
+            } catch (Exception e) {
+                System.err.println("  ❌ 查询择偶要求时发生异常: " + e.getMessage());
+            }
+        }
+        
+        return clientDetail;
+    }
+    
     @Override
     public ClientDetailVO getClientDetail(Integer resourceId) {
         System.out.println("=== MyResourceService.getClientDetail ===");

+ 2 - 0
service/homePage/src/main/java/com/zhentao/vo/ClientDetailVO.java

@@ -15,6 +15,8 @@ public class ClientDetailVO implements Serializable {
     // 基本信息(从my_resource表)
     @JsonProperty("resourceId")
     private Integer resourceId;
+    @JsonProperty("userId")
+    private Integer userId; // 用户ID(用于优质资源列表)
     private String name;
     private Integer age;
     private Integer gender;

+ 38 - 57
service/homePage/src/main/resources/mapper/MyResourceMapper.xml

@@ -159,67 +159,48 @@
     </select>
     
     <!-- 根据标签名称分页查询资源列表(关联users表获取头像) -->
+    <!-- 优质资源:查询已注册但没有被任何红娘绑定的用户 -->
     <select id="selectResourceListByTagName" resultMap="MyResourceVOMap">
         SELECT 
-            r.resource_id,
-            r.matchmaker_id,
-            r.name,
-            r.age,
-            r.gender,
-            r.constellation,
-            r.height,
-            r.weight,
-            r.marr_status,
-            r.diploma,
-            r.income,
-            r.address,
-            r.domicile,
-            r.occupation,
-            r.house,
-            r.phone,
-            r.backup_phone,
-            r.car,
-            r.mate_selection_criteria,
-            r.is_user,
-            r.user_id,
-            r.status,
-            r.reject_reason,
-            r.reward_points,
-            r.create_time,
-            r.update_time,
+            u.user_id as resource_id,
+            NULL as matchmaker_id,
+            u.nickname as name,
+            u.age,
+            u.gender,
+            u.constellation,
+            u.height,
+            u.weight,
+            u.marital_status as marr_status,
+            u.education as diploma,
+            u.income,
+            u.city as address,
+            u.hometown as domicile,
+            u.occupation,
+            u.house,
+            u.phone,
+            NULL as backup_phone,
+            u.car,
+            NULL as mate_selection_criteria,
+            1 as is_user,
+            u.user_id,
+            1 as status,
+            NULL as reject_reason,
+            0 as reward_points,
+            u.create_time,
+            u.update_time,
             u.avatar_url,
-            COALESCE(f.is_match, 0) as is_match,
-            COALESCE(f.is_invitation, 0) as is_invitation,
-            f.invitation_time
-        FROM my_resource r
-        LEFT JOIN users u ON r.user_id = u.user_id
-        LEFT JOIN (
-            SELECT f1.resource_id, f1.matchmaker_id, f1.is_match, f1.is_invitation, f1.invitation_time
-            FROM user_follow_up f1
-            INNER JOIN (
-                SELECT resource_id, matchmaker_id, MAX(update_time) as max_update_time
-                FROM user_follow_up
-                GROUP BY resource_id, matchmaker_id
-            ) f2 ON f1.resource_id = f2.resource_id 
-                AND f1.matchmaker_id = f2.matchmaker_id 
-                AND f1.update_time = f2.max_update_time
-        ) f ON r.resource_id = f.resource_id AND r.matchmaker_id = f.matchmaker_id
-        INNER JOIN my_resource_tag mrt ON r.resource_id = mrt.resource_id
-        INNER JOIN tag t ON mrt.tag_id = t.tag_id
-        WHERE t.tag_name = #{tagName} AND t.status = 1
-        AND r.is_user = 1
-        <if test="excludeMatchmakerId != null">
-            AND NOT EXISTS (
-                SELECT 1 
-                FROM my_resource mr 
-                WHERE mr.phone = r.phone 
-                AND mr.matchmaker_id = #{excludeMatchmakerId}
-            )
-        </if>
+            0 as is_match,
+            0 as is_invitation,
+            NULL as invitation_time
+        FROM users u
+        WHERE u.status = 1
+        AND NOT EXISTS (
+            SELECT 1 FROM my_resource mr WHERE mr.phone = u.phone
+        )
         <if test="keyword != null and keyword != ''">
-            AND (r.name LIKE CONCAT('%', #{keyword}, '%') 
-                 OR r.phone LIKE CONCAT('%', #{keyword}, '%'))
+            AND (u.nickname LIKE CONCAT('%', #{keyword}, '%') 
+                 OR u.phone LIKE CONCAT('%', #{keyword}, '%'))
         </if>
-        ORDER BY r.create_time DESC
+        ORDER BY u.create_time DESC
     </select>
 </mapper>