| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374 |
- /**
- * 运势计算工具类
- * 基于用户资料(生日、星座、生肖)计算婚恋运势、脱单指数、幸运推荐
- */
- 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
- }
|