|
|
@@ -27,22 +27,37 @@
|
|
|
|
|
|
<!-- 匹配方式选择 -->
|
|
|
<view class="match-modes">
|
|
|
- <view class="mode-item" @click="selectMode('smart')">
|
|
|
+ <view
|
|
|
+ class="mode-item"
|
|
|
+ :class="{ 'mode-item-active': selectedMode === 'smart' }"
|
|
|
+ @tap="selectMode('smart')"
|
|
|
+ >
|
|
|
<view class="mode-icon">🎯</view>
|
|
|
<view class="mode-title">智能算法</view>
|
|
|
<view class="mode-desc">基于兴趣爱好、性格特征智能匹配</view>
|
|
|
+ <view v-if="selectedMode === 'smart'" class="mode-selected">✓ 已选择</view>
|
|
|
</view>
|
|
|
|
|
|
- <view class="mode-item" @click="selectMode('online')">
|
|
|
+ <view
|
|
|
+ class="mode-item"
|
|
|
+ :class="{ 'mode-item-active': selectedMode === 'online' }"
|
|
|
+ @tap="selectMode('online')"
|
|
|
+ >
|
|
|
<view class="mode-icon">⚡</view>
|
|
|
<view class="mode-title">实时在线</view>
|
|
|
<view class="mode-desc">只匹配当前在线的优质用户</view>
|
|
|
+ <view v-if="selectedMode === 'online'" class="mode-selected">✓ 已选择</view>
|
|
|
</view>
|
|
|
|
|
|
- <view class="mode-item" @click="selectMode('precise')">
|
|
|
+ <view
|
|
|
+ class="mode-item"
|
|
|
+ :class="{ 'mode-item-active': selectedMode === 'precise' }"
|
|
|
+ @tap="selectMode('precise')"
|
|
|
+ >
|
|
|
<view class="mode-icon">💎</view>
|
|
|
<view class="mode-title">精准推荐</view>
|
|
|
<view class="mode-desc">根据您的偏好推荐最合适的对象</view>
|
|
|
+ <view v-if="selectedMode === 'precise'" class="mode-selected">✓ 已选择</view>
|
|
|
</view>
|
|
|
</view>
|
|
|
|
|
|
@@ -88,6 +103,8 @@
|
|
|
</template>
|
|
|
|
|
|
<script>
|
|
|
+import MATCH_API_CONFIG from '@/config/match-config.js'
|
|
|
+
|
|
|
export default {
|
|
|
data() {
|
|
|
return {
|
|
|
@@ -135,10 +152,17 @@ export default {
|
|
|
|
|
|
// 选择匹配模式
|
|
|
selectMode(mode) {
|
|
|
+ console.log('选择匹配模式:', mode);
|
|
|
this.selectedMode = mode;
|
|
|
+ const modeNames = {
|
|
|
+ 'smart': '智能算法',
|
|
|
+ 'online': '实时在线',
|
|
|
+ 'precise': '精准推荐'
|
|
|
+ };
|
|
|
uni.showToast({
|
|
|
- title: mode === 'smart' ? '智能算法' : mode === 'online' ? '实时在线' : '精准推荐',
|
|
|
- icon: 'none'
|
|
|
+ title: `已选择:${modeNames[mode] || mode}`,
|
|
|
+ icon: 'none',
|
|
|
+ duration: 1500
|
|
|
});
|
|
|
},
|
|
|
|
|
|
@@ -167,23 +191,26 @@ export default {
|
|
|
city: this.userInfo.city || '未知',
|
|
|
introduction: this.userInfo.introduction || '',
|
|
|
latitude: this.userInfo.latitude || null,
|
|
|
- longitude: this.userInfo.longitude || null
|
|
|
+ longitude: this.userInfo.longitude || null,
|
|
|
+ matchMode: this.selectedMode || 'smart' // 添加匹配模式
|
|
|
};
|
|
|
|
|
|
console.log('发送匹配请求:', matchData);
|
|
|
|
|
|
- // 调用匹配接口
|
|
|
- // 开发环境使用本地地址,生产环境使用服务器地址
|
|
|
- const baseUrl = 'http://localhost:8083'; // 本地开发
|
|
|
- // const baseUrl = 'http://115.190.125.125:8083'; // 生产环境
|
|
|
+ // 调用匹配接口 - 使用配置文件中的地址
|
|
|
+ const baseUrl = MATCH_API_CONFIG.BASE_URL;
|
|
|
+ const url = `${baseUrl}${MATCH_API_CONFIG.ENDPOINTS.START_MATCH}`;
|
|
|
+
|
|
|
+ console.log('匹配API地址:', url);
|
|
|
|
|
|
const [error, res] = await uni.request({
|
|
|
- url: `${baseUrl}/match/start`,
|
|
|
+ url: url,
|
|
|
method: 'POST',
|
|
|
header: {
|
|
|
'Content-Type': 'application/json'
|
|
|
},
|
|
|
- data: matchData
|
|
|
+ data: matchData,
|
|
|
+ timeout: 10000
|
|
|
});
|
|
|
|
|
|
console.log('匹配响应:', res);
|
|
|
@@ -214,14 +241,28 @@ export default {
|
|
|
return;
|
|
|
}
|
|
|
|
|
|
+ console.log('=== 匹配响应解析 ===');
|
|
|
+ console.log('完整响应:', JSON.stringify(res.data, null, 2));
|
|
|
+ console.log('code:', res.data.code);
|
|
|
+ console.log('status:', res.data.status);
|
|
|
+ console.log('msg:', res.data.msg);
|
|
|
+ console.log('data字段:', res.data.data);
|
|
|
+
|
|
|
if (res.data.code === 200) {
|
|
|
- console.log('=== 匹配成功,解析数据 ===');
|
|
|
- console.log('status:', res.data.status);
|
|
|
- console.log('完整data:', res.data.data);
|
|
|
-
|
|
|
if (res.data.status === 'success') {
|
|
|
// 立即匹配成功
|
|
|
- this.handleMatchSuccess(res.data.data);
|
|
|
+ const matchData = res.data.data;
|
|
|
+ if (!matchData) {
|
|
|
+ console.error('匹配成功但data为空');
|
|
|
+ this.isMatching = false;
|
|
|
+ this.matchStatus = '点击下方按钮开始匹配';
|
|
|
+ uni.showToast({
|
|
|
+ title: '匹配数据异常,请重试',
|
|
|
+ icon: 'none'
|
|
|
+ });
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ this.handleMatchSuccess(matchData);
|
|
|
} else if (res.data.status === 'waiting') {
|
|
|
// 等待匹配,开始轮询
|
|
|
this.matchStatus = '正在寻找合适的对象...';
|
|
|
@@ -255,45 +296,90 @@ export default {
|
|
|
|
|
|
// 开始轮询匹配状态
|
|
|
startPolling() {
|
|
|
- // 每2秒检查一次匹配状态(实际项目中可以用WebSocket)
|
|
|
- this.pollingTimer = setInterval(() => {
|
|
|
- // 这里可以调用一个查询匹配状态的接口
|
|
|
- // 暂时使用定时器模拟
|
|
|
- console.log('轮询匹配状态...');
|
|
|
- }, 2000);
|
|
|
+ let pollCount = 0;
|
|
|
+ const maxPolls = 15; // 最多轮询15次(30秒)
|
|
|
|
|
|
- // 30秒后停止匹配
|
|
|
- setTimeout(() => {
|
|
|
- if (this.isMatching) {
|
|
|
- this.cancelMatch();
|
|
|
- uni.showToast({
|
|
|
- title: '暂无合适的匹配对象,请稍后再试',
|
|
|
- icon: 'none'
|
|
|
- });
|
|
|
+ // 每2秒检查一次匹配状态
|
|
|
+ this.pollingTimer = setInterval(async () => {
|
|
|
+ pollCount++;
|
|
|
+ console.log(`轮询匹配状态 (${pollCount}/${maxPolls})...`);
|
|
|
+
|
|
|
+ // 如果超过最大轮询次数,停止匹配
|
|
|
+ if (pollCount >= maxPolls) {
|
|
|
+ if (this.isMatching) {
|
|
|
+ // 轮询超时,不显示取消匹配的提示,而是显示更合适的提示
|
|
|
+ this.cancelMatch(false);
|
|
|
+ uni.showToast({
|
|
|
+ title: '暂无合适的匹配对象,请稍后再试',
|
|
|
+ icon: 'none',
|
|
|
+ duration: 2000
|
|
|
+ });
|
|
|
+ }
|
|
|
+ return;
|
|
|
}
|
|
|
- }, 30000);
|
|
|
+
|
|
|
+ // 尝试查询匹配状态(如果后端有状态查询接口)
|
|
|
+ try {
|
|
|
+ const baseUrl = MATCH_API_CONFIG.BASE_URL;
|
|
|
+ const userId = String(this.userInfo.userId);
|
|
|
+
|
|
|
+ // 注意:这里假设后端有状态查询接口,如果没有可以注释掉
|
|
|
+ // const res = await uni.request({
|
|
|
+ // url: `${baseUrl}${MATCH_API_CONFIG.ENDPOINTS.MATCH_STATUS}?userId=${userId}`,
|
|
|
+ // method: 'GET'
|
|
|
+ // });
|
|
|
+ //
|
|
|
+ // if (res.data && res.data.code === 200 && res.data.status === 'success') {
|
|
|
+ // this.handleMatchSuccess(res.data.data);
|
|
|
+ // }
|
|
|
+ } catch (error) {
|
|
|
+ console.error('轮询查询失败:', error);
|
|
|
+ }
|
|
|
+ }, MATCH_API_CONFIG.CONFIG.POLLING_INTERVAL);
|
|
|
},
|
|
|
|
|
|
// 取消匹配
|
|
|
- async cancelMatch() {
|
|
|
+ // @param showToast 是否显示取消匹配的提示(默认true,轮询超时时传入false)
|
|
|
+ async cancelMatch(showToast = true) {
|
|
|
try {
|
|
|
- const baseUrl = 'http://localhost:8083'; // 本地开发
|
|
|
- // const baseUrl = 'http://115.190.125.125:8083'; // 生产环境
|
|
|
-
|
|
|
+ const baseUrl = MATCH_API_CONFIG.BASE_URL;
|
|
|
const userId = String(this.userInfo.userId);
|
|
|
- const res = await uni.request({
|
|
|
- url: `${baseUrl}/match/cancel?userId=${userId}`,
|
|
|
- method: 'POST'
|
|
|
- });
|
|
|
+ const url = `${baseUrl}${MATCH_API_CONFIG.ENDPOINTS.CANCEL_MATCH}?userId=${userId}`;
|
|
|
|
|
|
- console.log('取消匹配响应:', res.data);
|
|
|
+ console.log('取消匹配请求:', url);
|
|
|
|
|
|
- uni.showToast({
|
|
|
- title: '已取消匹配',
|
|
|
- icon: 'none'
|
|
|
+ const [error, res] = await uni.request({
|
|
|
+ url: url,
|
|
|
+ method: 'POST',
|
|
|
+ timeout: 5000
|
|
|
});
|
|
|
+
|
|
|
+ if (error) {
|
|
|
+ console.error('取消匹配请求失败:', error);
|
|
|
+ if (showToast) {
|
|
|
+ uni.showToast({
|
|
|
+ title: '取消匹配失败',
|
|
|
+ icon: 'none'
|
|
|
+ });
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ console.log('取消匹配响应:', res.data);
|
|
|
+ // 只有在需要显示提示时才显示
|
|
|
+ if (showToast && res.data && res.data.code === 200) {
|
|
|
+ uni.showToast({
|
|
|
+ title: res.data.msg || '已取消匹配',
|
|
|
+ icon: 'none'
|
|
|
+ });
|
|
|
+ }
|
|
|
+ }
|
|
|
} catch (error) {
|
|
|
console.error('取消匹配失败:', error);
|
|
|
+ if (showToast) {
|
|
|
+ uni.showToast({
|
|
|
+ title: '取消匹配失败',
|
|
|
+ icon: 'none'
|
|
|
+ });
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
this.isMatching = false;
|
|
|
@@ -309,6 +395,20 @@ export default {
|
|
|
handleMatchSuccess(data) {
|
|
|
console.log('=== 处理匹配成功数据 ===');
|
|
|
console.log('匹配数据:', data);
|
|
|
+ console.log('数据类型:', typeof data);
|
|
|
+ console.log('数据是否为null:', data === null);
|
|
|
+ console.log('数据是否为undefined:', data === undefined);
|
|
|
+
|
|
|
+ if (!data || typeof data !== 'object') {
|
|
|
+ console.error('匹配数据无效:', data);
|
|
|
+ this.isMatching = false;
|
|
|
+ this.matchStatus = '点击下方按钮开始匹配';
|
|
|
+ uni.showToast({
|
|
|
+ title: '匹配数据异常',
|
|
|
+ icon: 'none'
|
|
|
+ });
|
|
|
+ return;
|
|
|
+ }
|
|
|
|
|
|
this.isMatching = false;
|
|
|
this.matchStatus = '匹配成功!';
|
|
|
@@ -319,7 +419,7 @@ export default {
|
|
|
}
|
|
|
|
|
|
// 解析匹配数据 - 兼容不同的数据结构
|
|
|
- this.matchScore = Math.round(data.matchScore || data.roomId ? 50 : 0);
|
|
|
+ this.matchScore = Math.round(data.matchScore || (data.roomId ? 50 : 0));
|
|
|
|
|
|
// 尝试多种可能的数据结构
|
|
|
let matchedUserInfo = null;
|
|
|
@@ -546,6 +646,9 @@ export default {
|
|
|
margin-bottom: 24rpx;
|
|
|
box-shadow: 0 4rpx 12rpx rgba(0, 0, 0, 0.05);
|
|
|
transition: all 0.3s;
|
|
|
+ position: relative;
|
|
|
+ cursor: pointer;
|
|
|
+ -webkit-tap-highlight-color: transparent;
|
|
|
}
|
|
|
|
|
|
.mode-item:active {
|
|
|
@@ -553,6 +656,24 @@ export default {
|
|
|
box-shadow: 0 2rpx 8rpx rgba(0, 0, 0, 0.1);
|
|
|
}
|
|
|
|
|
|
+.mode-item-active {
|
|
|
+ background: linear-gradient(135deg, #FFF5F7 0%, #FFFFFF 100%);
|
|
|
+ border: 2rpx solid #E91E63;
|
|
|
+ box-shadow: 0 6rpx 20rpx rgba(233, 30, 99, 0.2);
|
|
|
+}
|
|
|
+
|
|
|
+.mode-selected {
|
|
|
+ position: absolute;
|
|
|
+ top: 16rpx;
|
|
|
+ right: 16rpx;
|
|
|
+ background: #E91E63;
|
|
|
+ color: white;
|
|
|
+ padding: 8rpx 16rpx;
|
|
|
+ border-radius: 20rpx;
|
|
|
+ font-size: 24rpx;
|
|
|
+ font-weight: bold;
|
|
|
+}
|
|
|
+
|
|
|
.mode-icon {
|
|
|
font-size: 60rpx;
|
|
|
text-align: center;
|