Procházet zdrojové kódy

Merge branch 'test_dev' into lisijia

李思佳 před 3 týdny
rodič
revize
639bd1a938

+ 253 - 186
LiangZhiYUMao/pages/astrology/index.vue

@@ -11,29 +11,46 @@
 			</view>
 		</view>
 
+		<!-- 用户资料提示 -->
+		<view class="profile-tip" v-if="!hasProfile" @click="goToProfile">
+			<view class="tip-content">
+				<text class="tip-icon">💫</text>
+				<view class="tip-text-group">
+					<text class="tip-title">完善资料,解锁专属运势</text>
+					<text class="tip-desc">填写出生日期,获取更精准的运势分析</text>
+				</view>
+				<text class="tip-arrow">→</text>
+			</view>
+		</view>
+		
+		<!-- 用户信息卡片 -->
+		<view class="user-profile-card" v-if="hasProfile" @click="goToProfile">
+			<view class="user-avatar-wrapper">
+				<image class="user-avatar" :src="userInfo.avatarUrl || userInfo.avatar || defaultAvatar" mode="aspectFill"></image>
+			</view>
+			<view class="user-info-content">
+				<text class="user-nickname">{{ userInfo.nickname || '用户' }}</text>
+				<view class="user-astro-tags">
+					<view class="astro-tag" v-if="userConstellation">
+						<text class="astro-icon">⭐</text>
+						<text class="astro-text">{{ userConstellation }}</text>
+					</view>
+					<view class="astro-tag" v-if="userZodiac">
+						<text class="astro-icon">🐲</text>
+						<text class="astro-text">属{{ userZodiac }}</text>
+					</view>
+				</view>
+			</view>
+			<view class="edit-icon">
+				<text>›</text>
+			</view>
+		</view>
+
 		<!-- 测算卡片区域 -->
 		<view class="cards-section">
 			<view class="card-item" v-for="(card, index) in cardList" :key="index" @click="handleCardClick(card)">
 				<view class="card-icon">{{ card.icon }}</view>
 				<view class="card-name">{{ card.name }}</view>
-				<view class="card-desc">{{ card.desc }}</view>
-			</view>
-		</view>
-
-		<!-- 星座配对测试 -->
-		<view class="match-test-banner" @click="handleConstellationMatch">
-			<view class="match-banner-content">
-				<view class="match-icon-group">
-					<text class="match-icon">💫</text>
-				</view>
-				<view class="match-text-group">
-					<view class="match-title">星座配对测试</view>
-					<view class="match-subtitle">测测你们的星座匹配度有多高</view>
-				</view>
-				<view class="match-arrow">→</view>
-			</view>
-			<view class="match-stats">
-				<text class="match-stats-text">💕 今日已有 {{ matchTestCount }} 对情侣测试</text>
 			</view>
 		</view>
 
@@ -101,172 +118,66 @@
 			</view>
 		</view>
 
-		<!-- 热门测试榜单 -->
-		<view class="hot-tests">
-			<view class="section-title">
-				<text class="title-text">🔥 热门测试榜单</text>
-				<text class="title-more">查看全部 ></text>
-			</view>
-			<view class="test-list">
-				<view class="test-item" v-for="(item, index) in hotTests" :key="index" @click="handleTestClick(item)">
-					<view class="test-rank" :class="{'top-rank': index < 3}">{{ index + 1 }}</view>
-					<view class="test-info">
-						<text class="test-name">{{ item.name }}</text>
-						<text class="test-count">{{ item.count }} 人已测</text>
-					</view>
-					<view class="test-tag" v-if="item.isNew">NEW</view>
-				</view>
-			</view>
-		</view>
-
 		<!-- 底部占位 -->
 		<view class="bottom-placeholder"></view>
 	</view>
 </template>
 
 <script>
+import fortuneUtil from '@/utils/fortune.js'
+import api from '@/utils/api.js'
+
 export default {
 	data() {
 		return {
 			// 今日日期
 			todayDate: '',
 			
+			// 用户信息
+			userInfo: {},
+			
+			// 是否有完整资料
+			hasProfile: false,
+			
+			// 用户星座和生肖
+			userConstellation: '',
+			userZodiac: '',
+			
+			// 默认头像
+			defaultAvatar: 'https://mmbiz.qpic.cn/mmbiz/icTdbqWNOwNRna42FI9FhqmIJtfQMh0LLicJxYS9xcd1u9YLnnvibALzycnOXLqm0JtmaNotzzSMyyibBtvBfzic6bg/0',
+			
 			// 测算卡片
 			cardList: [
-				{
-					id: 1,
-					name: '属相卡片',
-					icon: '🐷',
-					desc: '2.3万人测过',
-					type: 'zodiac'
-				},
-				{
-					id: 2,
-					name: '星座卡片',
-					icon: '♓',
-					desc: '2.3万人测过',
-					type: 'constellation'
-				},
-				{
-					id: 3,
-					name: '八字卡片',
-					icon: '☯',
-					desc: '2.3万人测过',
-					type: 'bazi'
-				},
-				{
-					id: 4,
-					name: 'MBTI卡片',
-					icon: '🧩',
-					desc: '2.3万人测过',
-					type: 'mbti'
-				}
+				{ id: 1, name: '属相卡片', icon: '🐷', type: 'zodiac' },
+				{ id: 2, name: '星座卡片', icon: '♓', type: 'constellation' },
+				{ id: 3, name: '八字卡片', icon: '☯', type: 'bazi' },
+				{ id: 4, name: 'MBTI卡片', icon: '🧩', type: 'mbti' }
 			],
 
-			// 缘分配对测试统计
-			matchTestCount: 1234,
-
-			// 我的爱情运势
-			loveFortune: [
-				{
-					label: '桃花运',
-					icon: '🌸',
-					score: 85,
-					color: 'linear-gradient(135deg, #FF6B9D 0%, #FFA5C6 100%)'
-				},
-				{
-					label: '爱情指数',
-					icon: '💕',
-					score: 78,
-					color: 'linear-gradient(135deg, #E91E63 0%, #FF6B9D 100%)'
-				},
-				{
-					label: '魅力值',
-					icon: '✨',
-					score: 92,
-					color: 'linear-gradient(135deg, #9C27B0 0%, #BA68C8 100%)'
-				}
-			],
+			// 我的爱情运势(动态计算)
+			loveFortune: [],
 
-			// 本周脱单指数
+			// 本周脱单指数(动态计算)
 			singleIndex: {
-				score: 88,
-				level: '极佳',
-				levelColor: 'linear-gradient(135deg, #FF6B6B 0%, #FF8E53 100%)',
-				tips: [
-					{ icon: '📅', text: '最佳约会日:周六' },
-					{ icon: '⏰', text: '最佳时间:下午2-5点' },
-					{ icon: '📍', text: '推荐地点:咖啡厅、公园' }
-				]
+				score: 75,
+				level: '良好',
+				levelColor: 'linear-gradient(135deg, #2196F3 0%, #03A9F4 100%)',
+				tips: []
 			},
 
-			// 每日幸运推荐
-			luckyRecommend: [
-				{
-					label: '幸运色',
-					icon: '🎨',
-					value: '粉红色',
-					bgColor: 'linear-gradient(135deg, #FFB6C1 0%, #FFE4E1 100%)'
-				},
-				{
-					label: '幸运数字',
-					icon: '🔢',
-					value: '7',
-					bgColor: 'linear-gradient(135deg, #9C27B0 0%, #CE93D8 100%)'
-				},
-				{
-					label: '约会建议',
-					icon: '💡',
-					value: '浪漫晚餐',
-					bgColor: 'linear-gradient(135deg, #FF9800 0%, #FFB74D 100%)'
-				},
-				{
-					label: '穿搭风格',
-					icon: '👗',
-					value: '清新甜美',
-					bgColor: 'linear-gradient(135deg, #4CAF50 0%, #81C784 100%)'
-				}
-			],
-
-			// 热门测试榜单
-			hotTests: [
-				{
-					id: 1,
-					name: '恋爱性格测试',
-					count: '12.8万',
-					isNew: false
-				},
-				{
-					id: 2,
-					name: '理想型匹配度',
-					count: '10.5万',
-					isNew: true
-				},
-				{
-					id: 3,
-					name: '爱情观测试',
-					count: '9.2万',
-					isNew: false
-				},
-				{
-					id: 4,
-					name: '婚姻契合度',
-					count: '8.6万',
-					isNew: false
-				},
-				{
-					id: 5,
-					name: '恋爱EQ测试',
-					count: '7.3万',
-					isNew: true
-				}
-			]
+			// 每日幸运推荐(动态计算)
+			luckyRecommend: []
 		}
 	},
 
 	onLoad() {
 		this.initData()
 	},
+	
+	onShow() {
+		// 每次显示页面时重新加载用户信息和计算运势
+		this.loadUserInfo()
+	},
 
 	methods: {
 		// 初始化数据
@@ -278,6 +189,63 @@ export default {
 			const weekDays = ['日', '一', '二', '三', '四', '五', '六']
 			const weekDay = weekDays[date.getDay()]
 			this.todayDate = `${month}月${day}日 周${weekDay}`
+			
+			// 加载用户信息并计算运势
+			this.loadUserInfo()
+		},
+		
+		// 加载用户信息
+		async loadUserInfo() {
+			// 先从本地存储获取基础信息
+			let userInfo = uni.getStorageSync('userInfo') || {}
+			const userId = uni.getStorageSync('userId')
+			
+			// 如果有userId,从API获取最新用户信息
+			if (userId) {
+				try {
+					const data = await api.user.getDetailInfo(userId)
+					if (data) {
+						// 合并API返回的数据
+						userInfo = {
+							...userInfo,
+							...data,
+							userId: userId
+						}
+						// 更新本地存储
+						uni.setStorageSync('userInfo', userInfo)
+						console.log('✅ 从API获取用户信息成功:', userInfo.nickname)
+					}
+				} catch (error) {
+					console.error('❌ 获取用户信息失败:', error)
+				}
+			}
+			
+			this.userInfo = userInfo
+			
+			// 计算运势
+			this.calculateFortune()
+		},
+		
+		// 计算运势数据
+		calculateFortune() {
+			const fortuneData = fortuneUtil.getFullFortuneData(this.userInfo)
+			
+			this.hasProfile = fortuneData.hasProfile
+			this.userConstellation = fortuneData.constellation || ''
+			this.userZodiac = fortuneData.zodiac || ''
+			this.loveFortune = fortuneData.loveFortune
+			this.singleIndex = fortuneData.singleIndex
+			this.luckyRecommend = fortuneData.luckyRecommend
+			
+			// 如果没有完整资料,显示提示
+			if (!this.hasProfile) {
+				console.log('用户资料不完整,显示默认运势数据')
+			} else {
+				console.log('根据用户资料计算运势:', {
+					constellation: this.userConstellation,
+					zodiac: this.userZodiac
+				})
+			}
 		},
 
 		// 返回上一页
@@ -320,18 +288,10 @@ export default {
 			}
 		},
 
-		// 星座配对测试
-		handleConstellationMatch() {
+		// 跳转到个人资料页面
+		goToProfile() {
 			uni.navigateTo({
-				url: '/pages/astrology/constellation-match'
-			})
-		},
-
-		// 测试项点击
-		handleTestClick(test) {
-			uni.showToast({
-				title: `${test.name}功能开发中`,
-				icon: 'none'
+				url: '/pages/profile/index'
 			})
 		}
 	}
@@ -385,6 +345,117 @@ export default {
 	}
 }
 
+/* 用户资料提示 */
+.profile-tip {
+	margin: 20rpx 30rpx;
+	background: linear-gradient(135deg, #FFF3E0 0%, #FFE0B2 100%);
+	border-radius: 16rpx;
+	padding: 24rpx;
+	box-shadow: 0 4rpx 12rpx rgba(255, 152, 0, 0.15);
+	
+	.tip-content {
+		display: flex;
+		align-items: center;
+		
+		.tip-icon {
+			font-size: 40rpx;
+			margin-right: 20rpx;
+		}
+		
+		.tip-text-group {
+			flex: 1;
+			
+			.tip-title {
+				font-size: 28rpx;
+				font-weight: 600;
+				color: #E65100;
+				display: block;
+				margin-bottom: 6rpx;
+			}
+			
+			.tip-desc {
+				font-size: 24rpx;
+				color: #FF8F00;
+			}
+		}
+		
+		.tip-arrow {
+			font-size: 32rpx;
+			color: #E65100;
+			font-weight: bold;
+		}
+	}
+}
+
+/* 用户信息卡片 */
+.user-profile-card {
+	display: flex;
+	align-items: center;
+	margin: 20rpx 30rpx;
+	padding: 24rpx;
+	background: linear-gradient(135deg, #FFFFFF 0%, #FFF9FB 100%);
+	border-radius: 20rpx;
+	box-shadow: 0 4rpx 16rpx rgba(233, 30, 99, 0.1);
+	border: 1rpx solid rgba(233, 30, 99, 0.1);
+	
+	.user-avatar-wrapper {
+		width: 100rpx;
+		height: 100rpx;
+		border-radius: 50%;
+		overflow: hidden;
+		margin-right: 24rpx;
+		border: 4rpx solid #FFE4EC;
+		box-shadow: 0 4rpx 12rpx rgba(233, 30, 99, 0.15);
+		
+		.user-avatar {
+			width: 100%;
+			height: 100%;
+		}
+	}
+	
+	.user-info-content {
+		flex: 1;
+		
+		.user-nickname {
+			font-size: 32rpx;
+			font-weight: 600;
+			color: #333333;
+			display: block;
+			margin-bottom: 12rpx;
+		}
+		
+		.user-astro-tags {
+			display: flex;
+			gap: 16rpx;
+			
+			.astro-tag {
+				display: flex;
+				align-items: center;
+				background: linear-gradient(135deg, #FCE4EC 0%, #F8BBD9 100%);
+				padding: 8rpx 16rpx;
+				border-radius: 20rpx;
+				
+				.astro-icon {
+					font-size: 22rpx;
+					margin-right: 6rpx;
+				}
+				
+				.astro-text {
+					font-size: 24rpx;
+					color: #E91E63;
+					font-weight: 500;
+				}
+			}
+		}
+	}
+	
+	.edit-icon {
+		font-size: 40rpx;
+		color: #CCCCCC;
+		font-weight: 300;
+	}
+}
+
 /* 测算卡片区域 */
 .cards-section {
 	display: flex;
@@ -420,12 +491,6 @@ export default {
 			font-size: 28rpx;
 			color: #333333;
 			font-weight: 500;
-			margin-bottom: 8rpx;
-		}
-
-		.card-desc {
-			font-size: 22rpx;
-			color: #999999;
 		}
 	}
 }
@@ -667,42 +732,44 @@ export default {
 
 	.lucky-grid {
 		display: grid;
-		grid-template-columns: repeat(2, 1fr);
-		gap: 20rpx;
+		grid-template-columns: repeat(4, 1fr);
+		gap: 16rpx;
 
 		.lucky-item {
 			display: flex;
 			flex-direction: column;
 			align-items: center;
 			background-color: #FFFFFF;
-			border-radius: 15rpx;
-			padding: 30rpx 20rpx;
+			border-radius: 12rpx;
+			padding: 20rpx 10rpx;
 			box-shadow: 0 4rpx 12rpx rgba(0, 0, 0, 0.06);
 
 			.lucky-icon-wrapper {
-				width: 80rpx;
-				height: 80rpx;
+				width: 60rpx;
+				height: 60rpx;
 				border-radius: 50%;
 				display: flex;
 				align-items: center;
 				justify-content: center;
-				margin-bottom: 15rpx;
+				margin-bottom: 10rpx;
 
 				.lucky-icon {
-					font-size: 40rpx;
+					font-size: 32rpx;
 				}
 			}
 
 			.lucky-label {
-				font-size: 24rpx;
+				font-size: 22rpx;
 				color: #999999;
-				margin-bottom: 8rpx;
+				margin-bottom: 6rpx;
 			}
 
 			.lucky-value {
-				font-size: 28rpx;
+				font-size: 24rpx;
 				color: #333333;
 				font-weight: 600;
+				text-align: center;
+				word-break: break-all;
 			}
 		}
 	}

+ 56 - 13
LiangZhiYUMao/pages/mine/my-dynamics.vue

@@ -216,14 +216,30 @@ export default {
             // 浏览记录列表数据
             browseList: [],
             // 默认头像
-            defaultAvatar: 'https://via.placeholder.com/100x100.png?text=头像'
+            defaultAvatar: 'https://via.placeholder.com/100x100.png?text=头像',
+            // 我的动态分页相关
+            dynamicPageNum: 1,
+            dynamicPageSize: 10,
+            dynamicLoading: false,
+            dynamicNoMore: false
         }
     },
   onLoad() {
     // 页面加载时获取用户信息和动态数据
     this.loadUserInfo();
+    // 初始化分页状态并加载第一页数据
+    this.dynamicPageNum = 1;
+    this.dynamicNoMore = false;
+    this.dynamicList = [];
     this.loadDynamicData();
   },
+  // 页面触底加载更多
+  onReachBottom() {
+    // 仅在“动态”标签下并且还有更多数据时加载
+    if (this.activeTab === 'dynamic' && !this.dynamicNoMore && !this.dynamicLoading) {
+      this.loadDynamicData();
+    }
+  },
   methods: {
         // 返回上一页
         goBack() {
@@ -248,6 +264,11 @@ export default {
       this.activeTab = tab;
       // 根据标签页加载对应数据
       if (tab === 'dynamic') {
+        // 切换回“动态”时,如果还没有数据或之前已经加载完一部分,继续使用当前分页状态
+        if (this.dynamicList.length === 0) {
+          this.dynamicPageNum = 1;
+          this.dynamicNoMore = false;
+        }
         this.loadDynamicData();
       } else if (tab === 'interaction') {
         this.loadInteractionData();
@@ -295,20 +316,42 @@ export default {
       }
     },
     // 加载动态数据
-    loadDynamicData() {
+    async loadDynamicData() {
       const userInfo = uni.getStorageSync('userInfo');
-      if (userInfo && userInfo.userId) {
-        // 获取用户发布的动态列表
-        api.dynamic.getUserDynamics(userInfo.userId, {
-          pageNum: 1,
-          pageSize: 10
-        }).then(res => {
-          if (res && res.records) {
-            this.dynamicList = res.records;
-          }
-        }).catch(err => {
-          console.error('获取用户动态列表失败:', err);
+      if (!userInfo || !userInfo.userId) {
+        return;
+      }
+      if (this.dynamicLoading || this.dynamicNoMore) {
+        return;
+      }
+
+      this.dynamicLoading = true;
+      try {
+        // 获取用户发布的动态列表(分页)
+        const res = await api.dynamic.getUserDynamics(userInfo.userId, {
+          pageNum: this.dynamicPageNum,
+          pageSize: this.dynamicPageSize
         });
+
+        if (res && res.records) {
+          const records = res.records || [];
+          if (this.dynamicPageNum === 1) {
+            this.dynamicList = records;
+          } else {
+            this.dynamicList = [...this.dynamicList, ...records];
+          }
+
+          // 根据返回数量判断是否还有更多
+          if (!records || records.length < this.dynamicPageSize) {
+            this.dynamicNoMore = true;
+          } else {
+            this.dynamicPageNum += 1;
+          }
+        }
+      } catch (err) {
+        console.error('获取用户动态列表失败:', err);
+      } finally {
+        this.dynamicLoading = false;
       }
     },
     // 加载互动数据

+ 374 - 0
LiangZhiYUMao/utils/fortune.js

@@ -0,0 +1,374 @@
+/**
+ * 运势计算工具类
+ * 基于用户资料(生日、星座、生肖)计算婚恋运势、脱单指数、幸运推荐
+ */
+
+import { getZodiacByBirthday, getZodiacInfo } from './zodiac.js'
+
+// 星座数据
+const CONSTELLATIONS = {
+	'白羊座': { element: '火', startDate: '03-21', endDate: '04-19', luckyColors: ['红色', '橙色'], luckyNumbers: [1, 9], personality: '热情冲动' },
+	'金牛座': { element: '土', startDate: '04-20', endDate: '05-20', luckyColors: ['绿色', '粉色'], luckyNumbers: [2, 6], personality: '稳重踏实' },
+	'双子座': { element: '风', startDate: '05-21', endDate: '06-21', luckyColors: ['黄色', '蓝色'], luckyNumbers: [3, 5], personality: '机智多变' },
+	'巨蟹座': { element: '水', startDate: '06-22', endDate: '07-22', luckyColors: ['白色', '银色'], luckyNumbers: [2, 7], personality: '温柔体贴' },
+	'狮子座': { element: '火', startDate: '07-23', endDate: '08-22', luckyColors: ['金色', '橙色'], luckyNumbers: [1, 5], personality: '自信大方' },
+	'处女座': { element: '土', startDate: '08-23', endDate: '09-22', luckyColors: ['灰色', '米色'], luckyNumbers: [4, 8], personality: '细心完美' },
+	'天秤座': { element: '风', startDate: '09-23', endDate: '10-23', luckyColors: ['粉色', '蓝色'], luckyNumbers: [6, 9], personality: '优雅和谐' },
+	'天蝎座': { element: '水', startDate: '10-24', endDate: '11-22', luckyColors: ['深红', '黑色'], luckyNumbers: [3, 9], personality: '神秘深情' },
+	'射手座': { element: '火', startDate: '11-23', endDate: '12-21', luckyColors: ['紫色', '蓝色'], luckyNumbers: [3, 7], personality: '乐观自由' },
+	'摩羯座': { element: '土', startDate: '12-22', endDate: '01-19', luckyColors: ['黑色', '深蓝'], luckyNumbers: [4, 8], personality: '务实稳重' },
+	'水瓶座': { element: '风', startDate: '01-20', endDate: '02-18', luckyColors: ['蓝色', '银色'], luckyNumbers: [4, 7], personality: '独立创新' },
+	'双鱼座': { element: '水', startDate: '02-19', endDate: '03-20', luckyColors: ['海蓝', '紫色'], luckyNumbers: [3, 9], personality: '浪漫敏感' }
+}
+
+// 约会建议库
+const DATE_SUGGESTIONS = [
+	'浪漫晚餐', '咖啡约会', '电影之夜', '公园散步', '逛街购物',
+	'看展览', '户外野餐', '游乐园', '密室逃脱', '烘焙体验',
+	'书店约会', '音乐会', '运动健身', '美食探店', '手工DIY'
+]
+
+// 穿搭风格库
+const STYLE_SUGGESTIONS = [
+	'清新甜美', '优雅知性', '休闲运动', '简约大方', '时尚潮流',
+	'温柔淑女', '帅气中性', '复古文艺', '可爱减龄', '成熟稳重'
+]
+
+// 幸运色库
+const LUCKY_COLORS = [
+	'粉红色', '天蓝色', '薄荷绿', '珊瑚橙', '薰衣草紫',
+	'米白色', '浅黄色', '玫瑰红', '湖蓝色', '杏色'
+]
+
+/**
+ * 根据生日获取星座
+ * @param {String} birthday - 生日,格式:YYYY-MM-DD
+ * @returns {String} 星座名称
+ */
+export function getConstellationByBirthday(birthday) {
+	if (!birthday) return null
+	
+	const parts = birthday.split('-')
+	const month = parseInt(parts[1])
+	const day = parseInt(parts[2])
+	const mmdd = `${month.toString().padStart(2, '0')}-${day.toString().padStart(2, '0')}`
+	
+	for (const [name, info] of Object.entries(CONSTELLATIONS)) {
+		const start = info.startDate
+		const end = info.endDate
+		
+		// 处理跨年的星座(摩羯座)
+		if (start > end) {
+			if (mmdd >= start || mmdd <= end) return name
+		} else {
+			if (mmdd >= start && mmdd <= end) return name
+		}
+	}
+	return '未知'
+}
+
+
+/**
+ * 获取基于日期的种子值(确保同一天结果一致)
+ * @param {Date} date - 日期
+ * @param {String} salt - 盐值(用于区分不同计算)
+ * @returns {Number} 种子值
+ */
+function getDaySeed(date, salt = '') {
+	const dateStr = `${date.getFullYear()}-${date.getMonth()}-${date.getDate()}-${salt}`
+	let hash = 0
+	for (let i = 0; i < dateStr.length; i++) {
+		const char = dateStr.charCodeAt(i)
+		hash = ((hash << 5) - hash) + char
+		hash = hash & hash
+	}
+	return Math.abs(hash)
+}
+
+/**
+ * 基于种子的伪随机数生成器
+ * @param {Number} seed - 种子值
+ * @param {Number} min - 最小值
+ * @param {Number} max - 最大值
+ * @returns {Number} 随机数
+ */
+function seededRandom(seed, min = 0, max = 100) {
+	const x = Math.sin(seed) * 10000
+	const random = x - Math.floor(x)
+	return Math.floor(random * (max - min + 1)) + min
+}
+
+/**
+ * 计算用户的婚恋运势
+ * @param {Object} userInfo - 用户信息 { birthDate, star, animal, gender }
+ * @returns {Array} 运势数组
+ */
+export function calculateLoveFortune(userInfo) {
+	const today = new Date()
+	const birthDate = userInfo.birthDate || userInfo.birth_date
+	
+	// 获取星座和生肖
+	const constellation = userInfo.star || (birthDate ? getConstellationByBirthday(birthDate) : null)
+	const zodiac = userInfo.animal || (birthDate ? getZodiacByBirthday(birthDate) : null)
+	
+	// 基础分数
+	let baseScore = 70
+	
+	// 根据星座元素调整基础分
+	if (constellation && CONSTELLATIONS[constellation]) {
+		const element = CONSTELLATIONS[constellation].element
+		const dayOfWeek = today.getDay()
+		
+		// 不同元素在不同日子有不同运势
+		if (element === '火' && (dayOfWeek === 2 || dayOfWeek === 4)) baseScore += 5
+		if (element === '土' && (dayOfWeek === 0 || dayOfWeek === 6)) baseScore += 5
+		if (element === '风' && (dayOfWeek === 1 || dayOfWeek === 3)) baseScore += 5
+		if (element === '水' && (dayOfWeek === 5)) baseScore += 5
+	}
+	
+	// 使用日期种子确保同一天结果一致
+	const seed1 = getDaySeed(today, `${constellation}-peach`)
+	const seed2 = getDaySeed(today, `${zodiac}-love`)
+	const seed3 = getDaySeed(today, `${constellation}-charm`)
+	
+	// 计算三项运势分数
+	const peachScore = Math.min(95, Math.max(60, baseScore + seededRandom(seed1, -10, 20)))
+	const loveScore = Math.min(95, Math.max(55, baseScore + seededRandom(seed2, -15, 18)))
+	const charmScore = Math.min(98, Math.max(65, baseScore + seededRandom(seed3, -5, 25)))
+	
+	return [
+		{
+			label: '桃花运',
+			icon: '🌸',
+			score: peachScore,
+			color: 'linear-gradient(135deg, #FF6B9D 0%, #FFA5C6 100%)'
+		},
+		{
+			label: '爱情指数',
+			icon: '💕',
+			score: loveScore,
+			color: 'linear-gradient(135deg, #E91E63 0%, #FF6B9D 100%)'
+		},
+		{
+			label: '魅力值',
+			icon: '✨',
+			score: charmScore,
+			color: 'linear-gradient(135deg, #9C27B0 0%, #BA68C8 100%)'
+		}
+	]
+}
+
+/**
+ * 计算本周脱单指数
+ * @param {Object} userInfo - 用户信息
+ * @returns {Object} 脱单指数数据
+ */
+export function calculateSingleIndex(userInfo) {
+	const today = new Date()
+	const birthDate = userInfo.birthDate || userInfo.birth_date
+	
+	// 获取星座和生肖
+	const constellation = userInfo.star || (birthDate ? getConstellationByBirthday(birthDate) : null)
+	const zodiac = userInfo.animal || (birthDate ? getZodiacByBirthday(birthDate) : null)
+	
+	// 获取本周的周一作为种子基准
+	const weekStart = new Date(today)
+	weekStart.setDate(today.getDate() - today.getDay() + 1)
+	
+	const seed = getDaySeed(weekStart, `${constellation}-${zodiac}-single`)
+	
+	// 计算基础分数
+	let score = seededRandom(seed, 65, 95)
+	
+	// 根据生肖特性微调
+	if (zodiac) {
+		const zodiacInfo = getZodiacInfo(zodiac)
+		if (zodiacInfo) {
+			// 社交型生肖加分
+			if (['鼠', '马', '猴', '猪'].includes(zodiac)) score += 3
+			// 内敛型生肖略减
+			if (['牛', '蛇', '羊'].includes(zodiac)) score -= 2
+		}
+	}
+	
+	score = Math.min(98, Math.max(50, score))
+	
+	// 确定等级
+	let level, levelColor
+	if (score >= 90) {
+		level = '极佳'
+		levelColor = 'linear-gradient(135deg, #FF6B6B 0%, #FF8E53 100%)'
+	} else if (score >= 80) {
+		level = '很好'
+		levelColor = 'linear-gradient(135deg, #4CAF50 0%, #8BC34A 100%)'
+	} else if (score >= 70) {
+		level = '良好'
+		levelColor = 'linear-gradient(135deg, #2196F3 0%, #03A9F4 100%)'
+	} else if (score >= 60) {
+		level = '一般'
+		levelColor = 'linear-gradient(135deg, #FF9800 0%, #FFC107 100%)'
+	} else {
+		level = '需努力'
+		levelColor = 'linear-gradient(135deg, #9E9E9E 0%, #BDBDBD 100%)'
+	}
+	
+	// 计算最佳约会日
+	const bestDaySeed = getDaySeed(weekStart, `${constellation}-bestday`)
+	const bestDayIndex = seededRandom(bestDaySeed, 0, 6)
+	const weekDays = ['周日', '周一', '周二', '周三', '周四', '周五', '周六']
+	const bestDay = weekDays[bestDayIndex]
+	
+	// 计算最佳时间段
+	const timeSeed = getDaySeed(weekStart, `${zodiac}-time`)
+	const timeSlots = ['上午10-12点', '下午2-5点', '傍晚5-7点', '晚上7-9点']
+	const bestTime = timeSlots[seededRandom(timeSeed, 0, 3)]
+	
+	// 推荐地点
+	const placeSeed = getDaySeed(weekStart, `${constellation}-place`)
+	const places = [
+		'咖啡厅、书店', '公园、广场', '商场、电影院', 
+		'餐厅、美食街', '展览馆、博物馆', '游乐园、景区'
+	]
+	const bestPlace = places[seededRandom(placeSeed, 0, 5)]
+	
+	return {
+		score,
+		level,
+		levelColor,
+		tips: [
+			{ icon: '📅', text: `最佳约会日:${bestDay}` },
+			{ icon: '⏰', text: `最佳时间:${bestTime}` },
+			{ icon: '📍', text: `推荐地点:${bestPlace}` }
+		]
+	}
+}
+
+
+/**
+ * 计算今日幸运推荐
+ * @param {Object} userInfo - 用户信息
+ * @returns {Array} 幸运推荐数组
+ */
+export function calculateLuckyRecommend(userInfo) {
+	const today = new Date()
+	const birthDate = userInfo.birthDate || userInfo.birth_date
+	
+	// 获取星座
+	const constellation = userInfo.star || (birthDate ? getConstellationByBirthday(birthDate) : null)
+	const zodiac = userInfo.animal || (birthDate ? getZodiacByBirthday(birthDate) : null)
+	
+	// 幸运色
+	let luckyColor = '粉红色'
+	if (constellation && CONSTELLATIONS[constellation]) {
+		const constellationColors = CONSTELLATIONS[constellation].luckyColors
+		const colorSeed = getDaySeed(today, `${constellation}-color`)
+		luckyColor = constellationColors[seededRandom(colorSeed, 0, constellationColors.length - 1)]
+	} else {
+		const colorSeed = getDaySeed(today, 'default-color')
+		luckyColor = LUCKY_COLORS[seededRandom(colorSeed, 0, LUCKY_COLORS.length - 1)]
+	}
+	
+	// 幸运数字
+	let luckyNumber = '7'
+	if (constellation && CONSTELLATIONS[constellation]) {
+		const constellationNumbers = CONSTELLATIONS[constellation].luckyNumbers
+		const numberSeed = getDaySeed(today, `${constellation}-number`)
+		luckyNumber = constellationNumbers[seededRandom(numberSeed, 0, constellationNumbers.length - 1)].toString()
+	} else {
+		const numberSeed = getDaySeed(today, 'default-number')
+		luckyNumber = seededRandom(numberSeed, 1, 9).toString()
+	}
+	
+	// 约会建议
+	const dateSeed = getDaySeed(today, `${zodiac}-date`)
+	const dateSuggestion = DATE_SUGGESTIONS[seededRandom(dateSeed, 0, DATE_SUGGESTIONS.length - 1)]
+	
+	// 穿搭风格
+	const styleSeed = getDaySeed(today, `${constellation}-style`)
+	const styleSuggestion = STYLE_SUGGESTIONS[seededRandom(styleSeed, 0, STYLE_SUGGESTIONS.length - 1)]
+	
+	return [
+		{
+			label: '幸运色',
+			icon: '🎨',
+			value: luckyColor,
+			bgColor: 'linear-gradient(135deg, #FFB6C1 0%, #FFE4E1 100%)'
+		},
+		{
+			label: '幸运数字',
+			icon: '🔢',
+			value: luckyNumber,
+			bgColor: 'linear-gradient(135deg, #9C27B0 0%, #CE93D8 100%)'
+		},
+		{
+			label: '约会建议',
+			icon: '💡',
+			value: dateSuggestion,
+			bgColor: 'linear-gradient(135deg, #FF9800 0%, #FFB74D 100%)'
+		},
+		{
+			label: '穿搭风格',
+			icon: '👗',
+			value: styleSuggestion,
+			bgColor: 'linear-gradient(135deg, #4CAF50 0%, #81C784 100%)'
+		}
+	]
+}
+
+/**
+ * 获取用户完整的运势数据
+ * @param {Object} userInfo - 用户信息
+ * @returns {Object} 完整运势数据
+ */
+export function getFullFortuneData(userInfo) {
+	// 检查用户是否有足够的资料
+	const birthDate = userInfo.birthDate || userInfo.birth_date
+	const hasProfile = birthDate || userInfo.star || userInfo.animal
+	
+	if (!hasProfile) {
+		// 返回默认数据并提示完善资料
+		return {
+			hasProfile: false,
+			message: '完善个人资料后可查看专属运势',
+			loveFortune: [
+				{ label: '桃花运', icon: '🌸', score: 75, color: 'linear-gradient(135deg, #FF6B9D 0%, #FFA5C6 100%)' },
+				{ label: '爱情指数', icon: '💕', score: 70, color: 'linear-gradient(135deg, #E91E63 0%, #FF6B9D 100%)' },
+				{ label: '魅力值', icon: '✨', score: 80, color: 'linear-gradient(135deg, #9C27B0 0%, #BA68C8 100%)' }
+			],
+			singleIndex: {
+				score: 75,
+				level: '良好',
+				levelColor: 'linear-gradient(135deg, #2196F3 0%, #03A9F4 100%)',
+				tips: [
+					{ icon: '📅', text: '最佳约会日:周六' },
+					{ icon: '⏰', text: '最佳时间:下午2-5点' },
+					{ icon: '📍', text: '推荐地点:咖啡厅、公园' }
+				]
+			},
+			luckyRecommend: [
+				{ label: '幸运色', icon: '🎨', value: '粉红色', bgColor: 'linear-gradient(135deg, #FFB6C1 0%, #FFE4E1 100%)' },
+				{ label: '幸运数字', icon: '🔢', value: '7', bgColor: 'linear-gradient(135deg, #9C27B0 0%, #CE93D8 100%)' },
+				{ label: '约会建议', icon: '💡', value: '浪漫晚餐', bgColor: 'linear-gradient(135deg, #FF9800 0%, #FFB74D 100%)' },
+				{ label: '穿搭风格', icon: '👗', value: '清新甜美', bgColor: 'linear-gradient(135deg, #4CAF50 0%, #81C784 100%)' }
+			]
+		}
+	}
+	
+	return {
+		hasProfile: true,
+		constellation: userInfo.star || (birthDate ? getConstellationByBirthday(birthDate) : null),
+		zodiac: userInfo.animal || (birthDate ? getZodiacByBirthday(birthDate) : null),
+		loveFortune: calculateLoveFortune(userInfo),
+		singleIndex: calculateSingleIndex(userInfo),
+		luckyRecommend: calculateLuckyRecommend(userInfo)
+	}
+}
+
+export default {
+	getConstellationByBirthday,
+	calculateLoveFortune,
+	calculateSingleIndex,
+	calculateLuckyRecommend,
+	getFullFortuneData,
+	CONSTELLATIONS
+}