| 12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235 |
- /**
- * 八字计算工具类
- * 基于传统命理学理论实现八字计算、分析和配对功能
- * 支持专业API验证和本地算法双重计算
- */
- import { BAZI_API_CONFIG } from '@/config/api-config.js'
- // 天干
- const TIANGAN = ['甲', '乙', '丙', '丁', '戊', '己', '庚', '辛', '壬', '癸']
- // 地支
- const DIZHI = ['子', '丑', '寅', '卯', '辰', '巳', '午', '未', '申', '酉', '戌', '亥']
- // 天干五行
- const TIANGAN_WUXING = {
- '甲': '木', '乙': '木',
- '丙': '火', '丁': '火',
- '戊': '土', '己': '土',
- '庚': '金', '辛': '金',
- '壬': '水', '癸': '水'
- }
- // 地支五行
- const DIZHI_WUXING = {
- '子': '水', '丑': '土', '寅': '木', '卯': '木',
- '辰': '土', '巳': '火', '午': '火', '未': '土',
- '申': '金', '酉': '金', '戌': '土', '亥': '水'
- }
- // 天干阴阳
- const TIANGAN_YINYANG = {
- '甲': '阳', '乙': '阴', '丙': '阳', '丁': '阴', '戊': '阳',
- '己': '阴', '庚': '阳', '辛': '阴', '壬': '阳', '癸': '阴'
- }
- // 地支阴阳
- const DIZHI_YINYANG = {
- '子': '阳', '丑': '阴', '寅': '阳', '卯': '阴', '辰': '阳', '巳': '阴',
- '午': '阳', '未': '阴', '申': '阳', '酉': '阴', '戌': '阳', '亥': '阴'
- }
- // 十二生肖
- const SHENGXIAO = ['鼠', '牛', '虎', '兔', '龙', '蛇', '马', '羊', '猴', '鸡', '狗', '猪']
- // 月份地支对照表(节气月)
- const MONTH_DIZHI = {
- 2: '寅', 3: '卯', 4: '辰', 5: '巳', 6: '午', 7: '未',
- 8: '申', 9: '酉', 10: '戌', 11: '亥', 12: '子', 1: '丑'
- }
- // 时辰对照表
- const TIME_DIZHI = {
- 23: '子', 0: '子', 1: '丑', 2: '丑', 3: '寅', 4: '寅',
- 5: '卯', 6: '卯', 7: '辰', 8: '辰', 9: '巳', 10: '巳',
- 11: '午', 12: '午', 13: '未', 14: '未', 15: '申', 16: '申',
- 17: '酉', 18: '酉', 19: '戌', 20: '戌', 21: '亥', 22: '亥'
- }
- // 五行生克关系
- const WUXING_RELATION = {
- '生': {
- '木': '火', '火': '土', '土': '金', '金': '水', '水': '木'
- },
- '克': {
- '木': '土', '火': '金', '土': '水', '金': '木', '水': '火'
- }
- }
- // 纳音表(简化版)
- const NAYIN = {
- '甲子': '海中金', '乙丑': '海中金', '丙寅': '炉中火', '丁卯': '炉中火',
- '戊辰': '大林木', '己巳': '大林木', '庚午': '路旁土', '辛未': '路旁土',
- '壬申': '剑锋金', '癸酉': '剑锋金', '甲戌': '山头火', '乙亥': '山头火',
- '丙子': '涧下水', '丁丑': '涧下水', '戊寅': '城头土', '己卯': '城头土',
- '庚辰': '白蜡金', '辛巳': '白蜡金', '壬午': '杨柳木', '癸未': '杨柳木',
- '甲申': '泉中水', '乙酉': '泉中水', '丙戌': '屋上土', '丁亥': '屋上土',
- '戊子': '霹雳火', '己丑': '霹雳火', '庚寅': '松柏木', '辛卯': '松柏木',
- '壬辰': '长流水', '癸巳': '长流水', '甲午': '砂中金', '乙未': '砂中金',
- '丙申': '山下火', '丁酉': '山下火', '戊戌': '平地木', '己亥': '平地木',
- '庚子': '壁上土', '辛丑': '壁上土', '壬寅': '金箔金', '癸卯': '金箔金',
- '甲辰': '佛灯火', '乙巳': '佛灯火', '丙午': '天河水', '丁未': '天河水',
- '戊申': '大驿土', '己酉': '大驿土', '庚戌': '钗钏金', '辛亥': '钗钏金',
- '壬子': '桑柘木', '癸丑': '桑柘木', '甲寅': '大溪水', '乙卯': '大溪水',
- '丙辰': '砂中土', '丁巳': '砂中土', '戊午': '天上火', '己未': '天上火',
- '庚申': '石榴木', '辛酉': '石榴木', '壬戌': '大海水', '癸亥': '大海水'
- }
- /**
- * 计算八字
- * @param {Date} birthDate 出生日期
- * @param {Number} hour 出生时辰(0-23)
- * @returns {Object} 八字信息
- */
- export function calculateBaZi(birthDate, hour) {
- const year = birthDate.getFullYear()
- const month = birthDate.getMonth() + 1
- const day = birthDate.getDate()
-
- // 计算年柱
- const yearGanZhi = getYearGanZhi(year)
-
- // 计算月柱
- const monthGanZhi = getMonthGanZhi(year, month)
-
- // 计算日柱
- const dayGanZhi = getDayGanZhi(year, month, day)
-
- // 计算时柱
- const hourGanZhi = getHourGanZhi(dayGanZhi.gan, hour)
-
- // 分析八字
- const analysis = analyzeBaZi({
- year: yearGanZhi,
- month: monthGanZhi,
- day: dayGanZhi,
- hour: hourGanZhi
- })
-
- return {
- year: yearGanZhi,
- month: monthGanZhi,
- day: dayGanZhi,
- hour: hourGanZhi,
- birthInfo: {
- year: year,
- month: month,
- day: day,
- hour: hour,
- shengxiao: SHENGXIAO[(year - 4) % 12],
- nayin: NAYIN[yearGanZhi.ganZhi] || '未知'
- },
- analysis: analysis,
- baziString: `${yearGanZhi.ganZhi} ${monthGanZhi.ganZhi} ${dayGanZhi.ganZhi} ${hourGanZhi.ganZhi}`,
- rizhu: dayGanZhi.ganZhi,
- riganWuxing: TIANGAN_WUXING[dayGanZhi.gan]
- }
- }
- /**
- * 获取年柱干支
- */
- function getYearGanZhi(year) {
- // 以1900年庚子年为基准计算
- const baseYear = 1900
- const yearOffset = year - baseYear
-
- const ganIndex = (yearOffset + 6) % 10 // 庚为第7个天干,索引为6
- const zhiIndex = (yearOffset + 0) % 12 // 子为第1个地支,索引为0
-
- const gan = TIANGAN[ganIndex]
- const zhi = DIZHI[zhiIndex]
-
- return {
- gan: gan,
- zhi: zhi,
- ganZhi: gan + zhi,
- wuxing: TIANGAN_WUXING[gan],
- yinyang: TIANGAN_YINYANG[gan]
- }
- }
- /**
- * 获取月柱干支
- */
- function getMonthGanZhi(year, month) {
- // 简化计算,实际应该根据节气
- const zhi = MONTH_DIZHI[month]
-
- // 月干计算:年干为甲己配丙寅,乙庚丁卯始...
- const yearGan = getYearGanZhi(year).gan
- let ganIndex = 0
-
- switch (yearGan) {
- case '甲': case '己': ganIndex = 2; break // 丙
- case '乙': case '庚': ganIndex = 3; break // 丁
- case '丙': case '辛': ganIndex = 4; break // 戊
- case '丁': case '壬': ganIndex = 5; break // 己
- case '戊': case '癸': ganIndex = 6; break // 庚
- }
-
- // 从寅月开始计算
- const monthOffset = month === 1 ? 11 : (month === 2 ? 0 : month - 2)
- ganIndex = (ganIndex + monthOffset) % 10
-
- const gan = TIANGAN[ganIndex]
-
- return {
- gan: gan,
- zhi: zhi,
- ganZhi: gan + zhi,
- wuxing: TIANGAN_WUXING[gan],
- yinyang: TIANGAN_YINYANG[gan]
- }
- }
- /**
- * 获取日柱干支(简化算法)
- */
- function getDayGanZhi(year, month, day) {
- // 以公元1年1月1日为甲子日计算(简化)
- const date = new Date(year, month - 1, day)
- const daysSince1900 = Math.floor((date - new Date(1900, 0, 1)) / (24 * 60 * 60 * 1000))
-
- // 1900年1月1日为庚戌日
- const ganIndex = (daysSince1900 + 6) % 10 // 庚的索引是6
- const zhiIndex = (daysSince1900 + 10) % 12 // 戌的索引是10
-
- const gan = TIANGAN[ganIndex]
- const zhi = DIZHI[zhiIndex]
-
- return {
- gan: gan,
- zhi: zhi,
- ganZhi: gan + zhi,
- wuxing: TIANGAN_WUXING[gan],
- yinyang: TIANGAN_YINYANG[gan]
- }
- }
- /**
- * 获取时柱干支
- */
- function getHourGanZhi(dayGan, hour) {
- const zhi = TIME_DIZHI[hour] || '未知'
-
- // 时干计算:甲己还是甲,乙庚丙作初...
- let ganIndex = 0
- const zhiIndex = DIZHI.indexOf(zhi)
-
- switch (dayGan) {
- case '甲': case '己': ganIndex = 0; break // 甲
- case '乙': case '庚': ganIndex = 2; break // 丙
- case '丙': case '辛': ganIndex = 4; break // 戊
- case '丁': case '壬': ganIndex = 6; break // 庚
- case '戊': case '癸': ganIndex = 8; break // 壬
- }
-
- ganIndex = (ganIndex + zhiIndex) % 10
- const gan = TIANGAN[ganIndex]
-
- return {
- gan: gan,
- zhi: zhi,
- ganZhi: gan + zhi,
- wuxing: TIANGAN_WUXING[gan],
- yinyang: TIANGAN_YINYANG[gan]
- }
- }
- /**
- * 分析八字
- */
- function analyzeBaZi(bazi) {
- const wuxingCount = countWuXing(bazi)
- const qiangRuo = analyzeQiangRuo(bazi, wuxingCount)
- const yongshen = getYongShen(bazi, wuxingCount, qiangRuo)
- const personality = getPersonality(bazi)
-
- return {
- wuxingCount: wuxingCount,
- qiangRuo: qiangRuo,
- yongshen: yongshen,
- personality: personality,
- summary: generateBaziSummary(bazi, wuxingCount, qiangRuo, yongshen)
- }
- }
- /**
- * 统计五行个数
- */
- function countWuXing(bazi) {
- const count = { '金': 0, '木': 0, '水': 0, '火': 0, '土': 0 }
-
- // 统计天干
- Object.values(bazi).forEach(pillar => {
- const ganWuxing = TIANGAN_WUXING[pillar.gan]
- const zhiWuxing = DIZHI_WUXING[pillar.zhi]
- if (ganWuxing) count[ganWuxing]++
- if (zhiWuxing) count[zhiWuxing]++
- })
-
- return count
- }
- /**
- * 分析日主强弱
- */
- function analyzeQiangRuo(bazi, wuxingCount) {
- const riganWuxing = TIANGAN_WUXING[bazi.day.gan]
- const riganCount = wuxingCount[riganWuxing]
-
- // 简化分析:看日干五行在八字中的个数
- if (riganCount >= 3) {
- return { type: '身旺', description: '日主偏强,需要消耗和克制' }
- } else if (riganCount <= 1) {
- return { type: '身弱', description: '日主偏弱,需要生助和帮扶' }
- } else {
- return { type: '中和', description: '日主适中,平衡发展' }
- }
- }
- /**
- * 取用神
- */
- function getYongShen(bazi, wuxingCount, qiangRuo) {
- const riganWuxing = TIANGAN_WUXING[bazi.day.gan]
-
- if (qiangRuo.type === '身旺') {
- // 身旺用克泄耗
- const keWuxing = Object.keys(WUXING_RELATION.克).find(key => WUXING_RELATION.克[key] === riganWuxing)
- const xieWuxing = WUXING_RELATION.生[riganWuxing]
- return {
- primary: keWuxing || xieWuxing,
- description: `日主${riganWuxing}偏旺,宜用${keWuxing || xieWuxing}调候`
- }
- } else if (qiangRuo.type === '身弱') {
- // 身弱用生扶
- const shengWuxing = Object.keys(WUXING_RELATION.生).find(key => WUXING_RELATION.生[key] === riganWuxing)
- return {
- primary: shengWuxing || riganWuxing,
- description: `日主${riganWuxing}偏弱,宜用${shengWuxing || riganWuxing}生扶`
- }
- } else {
- return {
- primary: riganWuxing,
- description: `日主${riganWuxing}中和,保持平衡即可`
- }
- }
- }
- /**
- * 获取性格特征
- */
- function getPersonality(bazi) {
- const traits = []
-
- // 根据日干分析性格
- const rigan = bazi.day.gan
- switch (rigan) {
- case '甲':
- traits.push('正直', '有领导力', '创新精神')
- break
- case '乙':
- traits.push('温和', '适应力强', '善于变通')
- break
- case '丙':
- traits.push('热情', '积极向上', '善于表达')
- break
- case '丁':
- traits.push('细心', '有艺术天赋', '内心温暖')
- break
- case '戊':
- traits.push('踏实', '稳重可靠', '包容心强')
- break
- case '己':
- traits.push('务实', '善于理财', '注重细节')
- break
- case '庚':
- traits.push('果断', '意志坚强', '正义感强')
- break
- case '辛':
- traits.push('细腻', '品味高雅', '追求完美')
- break
- case '壬':
- traits.push('聪明', '适应力强', '善于沟通')
- break
- case '癸':
- traits.push('智慧', '直觉敏锐', '内心丰富')
- break
- }
-
- return traits
- }
- /**
- * 生成八字总结
- */
- function generateBaziSummary(bazi, wuxingCount, qiangRuo, yongshen) {
- const riganWuxing = TIANGAN_WUXING[bazi.day.gan]
- const maxWuxing = Object.keys(wuxingCount).reduce((a, b) => wuxingCount[a] > wuxingCount[b] ? a : b)
- const minWuxing = Object.keys(wuxingCount).reduce((a, b) => wuxingCount[a] < wuxingCount[b] ? a : b)
-
- return `您的八字为${bazi.baziString},日主${bazi.day.gan}${riganWuxing},${qiangRuo.description}。` +
- `八字中${maxWuxing}较旺,${minWuxing}较弱,${yongshen.description}。` +
- `建议在生活中多接触${yongshen.primary}属性的事物,有利于运势提升。`
- }
- /**
- * 八字配对分析
- * @param {Object} bazi1 第一个人的八字
- * @param {Object} bazi2 第二个人的八字
- * @returns {Object} 配对结果
- */
- export function analyzeBaziMatch(bazi1, bazi2) {
- // 日干配对
- const riganMatch = analyzeRiganMatch(bazi1.day.gan, bazi2.day.gan)
-
- // 五行配对
- const wuxingMatch = analyzeWuxingMatch(bazi1.riganWuxing, bazi2.riganWuxing)
-
- // 纳音配对
- const nayinMatch = analyzeNayinMatch(bazi1.birthInfo.nayin, bazi2.birthInfo.nayin)
-
- // 生肖配对
- const shengxiaoMatch = analyzeShengxiaoMatch(bazi1.birthInfo.shengxiao, bazi2.birthInfo.shengxiao)
-
- // 综合评分
- const totalScore = calculateMatchScore(riganMatch, wuxingMatch, nayinMatch, shengxiaoMatch)
-
- // 获取配对等级
- const level = getMatchLevel(totalScore)
-
- return {
- totalScore: totalScore,
- level: level.name,
- levelColor: level.color,
- riganMatch: riganMatch,
- wuxingMatch: wuxingMatch,
- nayinMatch: nayinMatch,
- shengxiaoMatch: shengxiaoMatch,
- advantages: generateMatchAdvantages(bazi1, bazi2),
- challenges: generateMatchChallenges(bazi1, bazi2),
- suggestions: generateMatchSuggestions(bazi1, bazi2, totalScore),
- summary: generateMatchSummary(bazi1, bazi2, totalScore)
- }
- }
- /**
- * 分析日干配对
- */
- function analyzeRiganMatch(gan1, gan2) {
- const wuxing1 = TIANGAN_WUXING[gan1]
- const wuxing2 = TIANGAN_WUXING[gan2]
- const yinyang1 = TIANGAN_YINYANG[gan1]
- const yinyang2 = TIANGAN_YINYANG[gan2]
-
- let score = 50
- let description = ''
-
- // 阴阳配合
- if (yinyang1 !== yinyang2) {
- score += 15
- description += '阴阳互补,'
- }
-
- // 五行关系
- if (WUXING_RELATION.生[wuxing1] === wuxing2) {
- score += 20
- description += `${gan1}生${gan2},相生和谐`
- } else if (WUXING_RELATION.生[wuxing2] === wuxing1) {
- score += 20
- description += `${gan2}生${gan1},相生和谐`
- } else if (WUXING_RELATION.克[wuxing1] === wuxing2) {
- score -= 10
- description += `${gan1}克${gan2},需要包容`
- } else if (WUXING_RELATION.克[wuxing2] === wuxing1) {
- score -= 10
- description += `${gan2}克${gan1},需要理解`
- } else if (wuxing1 === wuxing2) {
- score += 10
- description += '同气相求,志趣相投'
- } else {
- description += '五行中和,平稳发展'
- }
-
- return {
- score: Math.max(0, Math.min(100, score)),
- description: description
- }
- }
- /**
- * 分析五行配对
- */
- function analyzeWuxingMatch(wuxing1, wuxing2) {
- let score = 60
- let description = ''
-
- if (wuxing1 === wuxing2) {
- score = 75
- description = `同属${wuxing1},价值观相近,容易理解对方`
- } else if (WUXING_RELATION.生[wuxing1] === wuxing2 || WUXING_RELATION.生[wuxing2] === wuxing1) {
- score = 85
- description = `${wuxing1}与${wuxing2}相生,互相促进,相得益彰`
- } else if (WUXING_RELATION.克[wuxing1] === wuxing2 || WUXING_RELATION.克[wuxing2] === wuxing1) {
- score = 40
- description = `${wuxing1}与${wuxing2}相克,需要更多理解和包容`
- } else {
- score = 65
- description = `${wuxing1}与${wuxing2}中性关系,互补性较好`
- }
-
- return {
- score: score,
- description: description
- }
- }
- /**
- * 分析纳音配对
- */
- function analyzeNayinMatch(nayin1, nayin2) {
- // 简化的纳音配对逻辑
- let score = 60
- let description = ''
-
- if (nayin1 === nayin2) {
- score = 70
- description = `同为${nayin1},命理相同,默契度高`
- } else {
- // 根据纳音五行分析
- const nayin1Wuxing = getNayinWuxing(nayin1)
- const nayin2Wuxing = getNayinWuxing(nayin2)
-
- if (nayin1Wuxing && nayin2Wuxing) {
- if (WUXING_RELATION.生[nayin1Wuxing] === nayin2Wuxing || WUXING_RELATION.生[nayin2Wuxing] === nayin1Wuxing) {
- score = 80
- description = `${nayin1}与${nayin2}纳音相生,天作之合`
- } else if (WUXING_RELATION.克[nayin1Wuxing] === nayin2Wuxing || WUXING_RELATION.克[nayin2Wuxing] === nayin1Wuxing) {
- score = 45
- description = `${nayin1}与${nayin2}纳音相克,需要调和`
- } else {
- score = 65
- description = `${nayin1}与${nayin2}纳音和谐,关系稳定`
- }
- } else {
- description = `${nayin1}与${nayin2},命理互补`
- }
- }
-
- return {
- score: score,
- description: description
- }
- }
- /**
- * 获取纳音五行
- */
- function getNayinWuxing(nayin) {
- if (nayin.includes('金')) return '金'
- if (nayin.includes('木')) return '木'
- if (nayin.includes('水')) return '水'
- if (nayin.includes('火')) return '火'
- if (nayin.includes('土')) return '土'
- return null
- }
- /**
- * 分析生肖配对
- */
- function analyzeShengxiaoMatch(shengxiao1, shengxiao2) {
- // 生肖配对表
- const shengxiaoCompatibility = {
- '鼠': { '龙': 90, '猴': 85, '牛': 80, '马': 30, '羊': 40 },
- '牛': { '蛇': 90, '鸡': 85, '鼠': 80, '马': 35, '羊': 30 },
- '虎': { '马': 90, '狗': 85, '猪': 80, '猴': 30, '蛇': 35 },
- '兔': { '羊': 90, '猪': 85, '狗': 80, '鸡': 30, '龙': 35 },
- '龙': { '鼠': 90, '猴': 85, '鸡': 80, '狗': 30, '兔': 35 },
- '蛇': { '牛': 90, '鸡': 85, '猴': 80, '猪': 30, '虎': 35 },
- '马': { '虎': 90, '狗': 85, '羊': 80, '鼠': 30, '牛': 35 },
- '羊': { '兔': 90, '马': 80, '猪': 85, '牛': 30, '鼠': 40 },
- '猴': { '鼠': 85, '龙': 85, '蛇': 80, '虎': 30, '猪': 35 },
- '鸡': { '牛': 85, '蛇': 85, '龙': 80, '兔': 30, '狗': 35 },
- '狗': { '虎': 85, '马': 85, '兔': 80, '龙': 30, '鸡': 35 },
- '猪': { '兔': 85, '羊': 85, '虎': 80, '蛇': 30, '猴': 35 }
- }
-
- let score = 60
- let description = ''
-
- if (shengxiao1 === shengxiao2) {
- score = 70
- description = `同属${shengxiao1},性格相似,容易产生共鸣`
- } else if (shengxiaoCompatibility[shengxiao1] && shengxiaoCompatibility[shengxiao1][shengxiao2]) {
- score = shengxiaoCompatibility[shengxiao1][shengxiao2]
- if (score >= 85) {
- description = `${shengxiao1}与${shengxiao2}是最佳配对,天生一对`
- } else if (score >= 70) {
- description = `${shengxiao1}与${shengxiao2}配对良好,相处融洽`
- } else {
- description = `${shengxiao1}与${shengxiao2}需要更多磨合,相互理解`
- }
- } else {
- description = `${shengxiao1}与${shengxiao2}属于中性配对,平稳发展`
- }
-
- return {
- score: score,
- description: description
- }
- }
- /**
- * 计算总体配对分数
- */
- function calculateMatchScore(riganMatch, wuxingMatch, nayinMatch, shengxiaoMatch) {
- // 加权计算
- const weights = {
- rigan: 0.3, // 日干权重30%
- wuxing: 0.3, // 五行权重30%
- nayin: 0.2, // 纳音权重20%
- shengxiao: 0.2 // 生肖权重20%
- }
-
- const totalScore =
- riganMatch.score * weights.rigan +
- wuxingMatch.score * weights.wuxing +
- nayinMatch.score * weights.nayin +
- shengxiaoMatch.score * weights.shengxiao
-
- return Math.round(totalScore)
- }
- /**
- * 获取配对等级
- */
- function getMatchLevel(score) {
- if (score >= 90) {
- return { name: '天作之合', color: 'linear-gradient(135deg, #FF6B9D 0%, #FFA5C6 100%)' }
- } else if (score >= 80) {
- return { name: '绝配佳偶', color: 'linear-gradient(135deg, #4CAF50 0%, #81C784 100%)' }
- } else if (score >= 70) {
- return { name: '良缘美眷', color: 'linear-gradient(135deg, #2196F3 0%, #64B5F6 100%)' }
- } else if (score >= 60) {
- return { name: '尚可之配', color: 'linear-gradient(135deg, #FF9800 0%, #FFB74D 100%)' }
- } else if (score >= 50) {
- return { name: '需要磨合', color: 'linear-gradient(135deg, #FFC107 0%, #FFD54F 100%)' }
- } else {
- return { name: '挑战较大', color: 'linear-gradient(135deg, #F44336 0%, #EF5350 100%)' }
- }
- }
- /**
- * 生成配对优势
- */
- function generateMatchAdvantages(bazi1, bazi2) {
- const advantages = []
-
- // 分析共同特点
- const commonTraits = bazi1.analysis.personality.filter(trait =>
- bazi2.analysis.personality.includes(trait)
- )
-
- if (commonTraits.length > 0) {
- advantages.push(`你们都具有${commonTraits.join('、')}的特质,容易产生共鸣和理解`)
- }
-
- // 分析互补特点
- if (bazi1.analysis.qiangRuo.type === '身旺' && bazi2.analysis.qiangRuo.type === '身弱') {
- advantages.push('一强一弱的组合,能够互相补充,形成良好的平衡')
- } else if (bazi1.analysis.qiangRuo.type === '身弱' && bazi2.analysis.qiangRuo.type === '身旺') {
- advantages.push('强弱互补的搭配,能够相互扶持,共同成长')
- }
-
- // 分析用神关系
- if (bazi1.analysis.yongshen.primary === bazi2.riganWuxing) {
- advantages.push('对方的日主五行正好是您的用神,能够给您带来很好的帮助')
- }
-
- return advantages.length > 0 ? advantages : ['你们的八字搭配有其独特的魅力,能够在相处中发现彼此的闪光点']
- }
- /**
- * 生成配对挑战
- */
- function generateMatchChallenges(bazi1, bazi2) {
- const challenges = []
-
- // 分析冲突
- if (bazi1.riganWuxing && bazi2.riganWuxing &&
- WUXING_RELATION.克[bazi1.riganWuxing] === bazi2.riganWuxing) {
- challenges.push('日主五行相克,在性格和处事方式上可能存在一些分歧')
- }
-
- // 分析过旺或过弱
- if (bazi1.analysis.qiangRuo.type === '身旺' && bazi2.analysis.qiangRuo.type === '身旺') {
- challenges.push('双方都比较强势,在决策时可能需要更多的沟通和协调')
- } else if (bazi1.analysis.qiangRuo.type === '身弱' && bazi2.analysis.qiangRuo.type === '身弱') {
- challenges.push('双方都比较内敛,需要主动创造更多的交流机会')
- }
-
- return challenges.length > 0 ? challenges : ['每一对组合都有需要磨合的地方,这正是相处的乐趣所在']
- }
- /**
- * 生成配对建议
- */
- function generateMatchSuggestions(bazi1, bazi2, totalScore) {
- const suggestions = []
-
- if (totalScore >= 80) {
- suggestions.push('你们的八字配对很好,珍惜这份缘分,相互支持共同成长')
- } else if (totalScore >= 60) {
- suggestions.push('你们的配对有很好的基础,多一些包容和理解,感情会更加稳定')
- } else {
- suggestions.push('缘分需要用心经营,多沟通多理解,用爱化解所有的不合')
- }
-
- // 根据用神给建议
- if (bazi1.analysis.yongshen.primary && bazi2.analysis.yongshen.primary) {
- const commonYongshen = bazi1.analysis.yongshen.primary === bazi2.analysis.yongshen.primary
- if (commonYongshen) {
- suggestions.push(`你们的用神都是${bazi1.analysis.yongshen.primary},可以一起从事相关的活动来增进感情`)
- }
- }
-
- suggestions.push('建议选择有利于双方用神的环境和时间进行重要的决策和沟通')
-
- return suggestions
- }
- /**
- * 生成配对总结
- */
- function generateMatchSummary(bazi1, bazi2, totalScore) {
- const level = getMatchLevel(totalScore)
- const summary = `您的八字${bazi1.baziString}与对方的八字${bazi2.baziString},` +
- `综合评分${totalScore}分,属于"${level.name}"的配对等级。`
-
- if (totalScore >= 80) {
- return summary + '你们的八字搭配很好,是难得的良缘,要好好珍惜。'
- } else if (totalScore >= 60) {
- return summary + '你们有着不错的缘分基础,通过相互理解和包容,能够建立美好的关系。'
- } else {
- return summary + '虽然八字配对有些挑战,但真爱能够化解一切,只要相互理解,同样能够获得幸福。'
- }
- }
- /**
- * 智能API选择器 - 根据策略选择最佳API
- * @returns {Object} 选中的API配置
- */
- function selectBestAPI() {
- const settings = BAZI_API_CONFIG.SETTINGS
- const enabledAPIs = settings.ENABLED_APIS
-
- // 按优先级排序可用的API
- const sortedAPIs = enabledAPIs
- .map(apiName => ({
- name: apiName,
- config: BAZI_API_CONFIG[apiName],
- isConfigured: BAZI_API_CONFIG[apiName].API_KEY &&
- !BAZI_API_CONFIG[apiName].API_KEY.startsWith('YOUR_')
- }))
- .filter(api => api.isConfigured)
- .sort((a, b) => a.config.PRIORITY - b.config.PRIORITY)
-
- if (sortedAPIs.length === 0) {
-
- return null
- }
-
- // 根据策略选择API
- switch (settings.STRATEGY) {
- case 'cost_first':
- return sortedAPIs.sort((a, b) => a.config.COST_PER_CALL - b.config.COST_PER_CALL)[0]
- case 'accuracy_first':
- return sortedAPIs[0] // 优先级最高的通常最准确
- case 'speed_first':
- return sortedAPIs.find(api => api.name === 'ALIYUN_API') || sortedAPIs[0]
- default:
- return sortedAPIs[0]
- }
- }
- /**
- * 调用专业八字API获取准确数据(支持多API自动切换)
- * @param {Date} birthDate 出生日期
- * @param {Number} hour 出生时辰(0-23)
- * @returns {Promise<Object>} API返回结果
- */
- export async function getBaziFromAPI(birthDate, hour) {
- const settings = BAZI_API_CONFIG.SETTINGS
- const maxRetries = settings.RETRY_COUNT || 2
-
- for (let attempt = 0; attempt < maxRetries + 1; attempt++) {
- try {
-
-
- // 智能选择API
- const selectedAPI = selectBestAPI()
- if (!selectedAPI) {
-
- return null
- }
-
-
- const result = await callSpecificAPI(selectedAPI, birthDate, hour)
- if (result) {
-
- return {
- ...result,
- apiProvider: selectedAPI.name,
- apiCost: selectedAPI.config.COST_PER_CALL
- }
- }
-
- // 如果启用自动故障转移,尝试下一个API
- if (settings.AUTO_FAILOVER && attempt < maxRetries) {
-
- const index = settings.ENABLED_APIS.indexOf(selectedAPI.name)
- if (index > -1) {
- settings.ENABLED_APIS.splice(index, 1)
- }
- continue
- }
-
- } catch (error) {
- console.error(`❌ API调用异常 (尝试${attempt + 1}):`, error)
- if (attempt === maxRetries) {
-
- return null
- }
- }
- }
-
- return null
- }
- /**
- * 调用特定的API服务
- * @param {Object} selectedAPI 选中的API配置
- * @param {Date} birthDate 出生日期
- * @param {Number} hour 出生时辰
- * @returns {Promise<Object>} API返回结果
- */
- async function callSpecificAPI(selectedAPI, birthDate, hour) {
- const { name, config } = selectedAPI
-
- // 根据不同API构建请求参数
- let params, url
-
- switch (name) {
- case 'JISU_API':
- params = {
- appkey: config.API_KEY,
- name: '用户', // 姓名参数(必填)
- city: '', // 城市参数(必填,可空)
- year: birthDate.getFullYear(),
- month: birthDate.getMonth() + 1,
- day: birthDate.getDate(),
- hour: hour,
- minute: 0, // 分钟,默认0
- sex: 1, // 性别,1男0女,默认男
- islunar: 0, // 是否阴历,0阳历1阴历
- istaiyang: 0, // 是否太阳时,0不使用1使用
- islunarmonth: 2 // 是否闰月,1是2否
- }
- url = `${config.BASE_URL}${config.ENDPOINTS.bazi}`
- break
-
- case 'JUHE_API':
- params = {
- key: config.API_KEY,
- year: birthDate.getFullYear(),
- month: birthDate.getMonth() + 1,
- day: birthDate.getDate(),
- hour: hour
- }
- url = `${config.BASE_URL}${config.ENDPOINTS.bazi}`
- break
-
- case 'ALIYUN_API':
- params = {
- year: birthDate.getFullYear(),
- month: birthDate.getMonth() + 1,
- day: birthDate.getDate(),
- hour: hour
- }
- url = `${config.BASE_URL}${config.ENDPOINTS.bazi}`
- break
-
- case 'TENCENT_API':
- params = {
- year: birthDate.getFullYear(),
- month: birthDate.getMonth() + 1,
- day: birthDate.getDate(),
- hour: hour
- }
- url = `${config.BASE_URL}${config.ENDPOINTS.bazi}`
- break
-
- default:
- console.error('❌ 不支持的API类型:', name)
- return null
- }
-
-
- // 发送请求
- const response = await new Promise((resolve, reject) => {
- const headers = {}
-
- // 阿里云和腾讯云需要特殊的认证头
- if (name === 'ALIYUN_API') {
- headers['Authorization'] = `APPCODE ${config.API_KEY}`
- } else if (name === 'TENCENT_API') {
- headers['Authorization'] = config.API_KEY
- }
-
- uni.request({
- url: url,
- data: params,
- method: 'GET',
- header: headers,
- timeout: BAZI_API_CONFIG.SETTINGS.TIMEOUT || 10000,
- success: (res) => {
-
- resolve(res)
- },
- fail: (err) => {
- console.error('📡 API请求失败:', err)
- reject(err)
- }
- })
- })
-
- // 解析不同API的响应格式
- return parseAPIResponse(name, response)
- }
- /**
- * 解析不同API的响应格式
- * @param {String} apiName API名称
- * @param {Object} response 响应对象
- * @returns {Object} 标准化的八字数据
- */
- function parseAPIResponse(apiName, response) {
- if (response.statusCode !== 200) {
- throw new Error(`HTTP ${response.statusCode}`)
- }
-
- const data = response.data
- let result = null
-
- switch (apiName) {
- case 'JISU_API':
- if (data.status === 0 && data.result) {
- result = data.result
- // 极速数据API返回的是完整的八字排盘数据
-
- }
- break
-
- case 'JUHE_API':
- if (data.error_code === 0 && data.result) {
- result = data.result
- }
- break
-
- case 'ALIYUN_API':
- case 'TENCENT_API':
- if (data.code === 200 && data.data) {
- result = data.data
- }
- break
- }
-
- if (!result) {
-
- return null
- }
-
- // 极速数据API专用解析(更丰富的数据)
- if (apiName === 'JISU_API' && result.bazi) {
- // 解析八字数组 [年柱, 月柱, 日柱, 时柱]
- const baziArray = result.bazi
- const nayinArray = result.nayin || []
-
- return {
- year: {
- gan: baziArray[0]?.charAt(0) || '',
- zhi: baziArray[0]?.charAt(1) || '',
- ganZhi: baziArray[0] || '',
- nayin: nayinArray[0] || ''
- },
- month: {
- gan: baziArray[1]?.charAt(0) || '',
- zhi: baziArray[1]?.charAt(1) || '',
- ganZhi: baziArray[1] || '',
- nayin: nayinArray[1] || ''
- },
- day: {
- gan: baziArray[2]?.charAt(0) || '',
- zhi: baziArray[2]?.charAt(1) || '',
- ganZhi: baziArray[2] || '',
- nayin: nayinArray[2] || ''
- },
- hour: {
- gan: baziArray[3]?.charAt(0) || '',
- zhi: baziArray[3]?.charAt(1) || '',
- ganZhi: baziArray[3] || '',
- nayin: nayinArray[3] || ''
- },
- baziString: baziArray.join(' '),
-
- // 极速数据提供的专业信息
- animal: result.animal, // 生肖
- yearganzhi: result.yearganzhi, // 年干支
- taiyuan: result.taiyuan, // 胎元
- minggong: result.minggong, // 命宫
- xunkong: result.xunkong, // 旬空
- qiyun: result.qiyun, // 起运时间
- jiaoyun: result.jiaoyun, // 交运时间
- qiankunzao: result.qiankunzao, // 乾造/坤造
- shensha: result.shensha, // 神煞
- dayun: result.dayun, // 大运
- liunian: result.liunian, // 流年
-
- // 农历信息
- lunar: {
- year: result.lunaryear,
- month: result.lunarmonth,
- day: result.lunarday,
- hour: result.lunarhour
- },
-
- // 节气信息
- jieqi: {
- prev: result.jieqiprev,
- next: result.jieqinext
- },
-
- source: 'api',
- apiProvider: 'jisuapi',
- apiData: result
- }
- }
-
- // 通用API数据格式(其他API使用)
- return {
- year: {
- gan: result.year_gan || result.yearGan,
- zhi: result.year_zhi || result.yearZhi,
- ganZhi: (result.year_gan || result.yearGan) + (result.year_zhi || result.yearZhi),
- wuxing: result.year_wuxing || result.yearWuxing,
- yinyang: result.year_yinyang || result.yearYinyang
- },
- month: {
- gan: result.month_gan || result.monthGan,
- zhi: result.month_zhi || result.monthZhi,
- ganZhi: (result.month_gan || result.monthGan) + (result.month_zhi || result.monthZhi),
- wuxing: result.month_wuxing || result.monthWuxing,
- yinyang: result.month_yinyang || result.monthYinyang
- },
- day: {
- gan: result.day_gan || result.dayGan,
- zhi: result.day_zhi || result.dayZhi,
- ganZhi: (result.day_gan || result.dayGan) + (result.day_zhi || result.dayZhi),
- wuxing: result.day_wuxing || result.dayWuxing,
- yinyang: result.day_yinyang || result.dayYinyang
- },
- hour: {
- gan: result.hour_gan || result.hourGan,
- zhi: result.hour_zhi || result.hourZhi,
- ganZhi: (result.hour_gan || result.hourGan) + (result.hour_zhi || result.hourZhi),
- wuxing: result.hour_wuxing || result.hourWuxing,
- yinyang: result.hour_yinyang || result.hourYinyang
- },
- baziString: `${result.year_gan || result.yearGan}${result.year_zhi || result.yearZhi} ${result.month_gan || result.monthGan}${result.month_zhi || result.monthZhi} ${result.day_gan || result.dayGan}${result.day_zhi || result.dayZhi} ${result.hour_gan || result.hourGan}${result.hour_zhi || result.hourZhi}`,
- nayin: result.nayin || '',
- source: 'api',
- apiData: result
- }
- }
- /**
- * 增强版八字计算(API + 本地算法)
- * @param {Date} birthDate 出生日期
- * @param {Number} hour 出生时辰(0-23)
- * @returns {Object} 八字信息
- */
- export async function calculateEnhancedBaZi(birthDate, hour) {
- let localResult = null
- let apiResult = null
-
- try {
- // 1. 先计算本地结果
- localResult = calculateBaZi(birthDate, hour)
-
-
- // 2. 尝试获取API结果
- if (BAZI_API_CONFIG.SETTINGS.ENABLE_VALIDATION) {
- apiResult = await getBaziFromAPI(birthDate, hour)
- }
-
- // 3. 结果对比和融合
- if (apiResult) {
-
-
- const comparison = compareBaziResults(localResult, apiResult)
-
- if (comparison.accuracy >= 0.8) {
-
- localResult.validation = {
- status: 'verified',
- accuracy: comparison.accuracy,
- apiSource: 'professional',
- differences: comparison.differences
- }
- } else {
-
- const enhancedResult = mergeApiAndLocalResults(apiResult, localResult)
- enhancedResult.validation = {
- status: 'api_corrected',
- accuracy: comparison.accuracy,
- apiSource: 'professional',
- differences: comparison.differences
- }
- return enhancedResult
- }
- } else {
- localResult.validation = {
- status: 'local_only',
- accuracy: 0.85, // 本地算法估计准确度
- apiSource: 'none',
- note: '建议配置专业API以提高准确度'
- }
- }
-
- return localResult
-
- } catch (error) {
- console.error('❌ 增强版八字计算异常:', error)
- return localResult || calculateBaZi(birthDate, hour)
- }
- }
- /**
- * 对比八字计算结果
- * @param {Object} localResult 本地算法结果
- * @param {Object} apiResult API算法结果
- * @returns {Object} 对比结果
- */
- function compareBaziResults(localResult, apiResult) {
- const differences = []
- let correctCount = 0
- let totalCount = 8 // 四柱共8个字
-
- // 对比四柱
- const pillars = ['year', 'month', 'day', 'hour']
- pillars.forEach(pillar => {
- if (localResult[pillar].gan === apiResult[pillar].gan) {
- correctCount++
- } else {
- differences.push(`${pillar}干: 本地${localResult[pillar].gan} vs API${apiResult[pillar].gan}`)
- }
-
- if (localResult[pillar].zhi === apiResult[pillar].zhi) {
- correctCount++
- } else {
- differences.push(`${pillar}支: 本地${localResult[pillar].zhi} vs API${apiResult[pillar].zhi}`)
- }
- })
-
- const accuracy = correctCount / totalCount
-
- return {
- accuracy: accuracy,
- differences: differences,
- recommendation: accuracy >= 0.8 ? 'use_local' : 'use_api'
- }
- }
- /**
- * 融合API和本地结果
- * @param {Object} apiResult API结果
- * @param {Object} localResult 本地结果
- * @returns {Object} 融合后的结果
- */
- function mergeApiAndLocalResults(apiResult, localResult) {
- // 以API结果为准,但保留本地的详细分析
- return {
- ...apiResult,
- // 保留本地的详细分析
- analysis: localResult.analysis,
- birthInfo: {
- ...localResult.birthInfo,
- // 如果API提供了纳音,使用API的
- nayin: apiResult.nayin || localResult.birthInfo.nayin
- },
- // 标记数据来源
- dataSource: 'api_enhanced',
- localCalculation: localResult.baziString,
- apiCalculation: apiResult.baziString
- }
- }
- /**
- * 获取八字建议
- */
- export function getBaziSuggestions(bazi) {
- const suggestions = []
-
- // 根据验证状态添加可靠性说明
- if (bazi.validation) {
- if (bazi.validation.status === 'verified') {
- suggestions.push(`✅ 您的八字经过专业API验证,准确度${Math.round(bazi.validation.accuracy * 100)}%,结果可信度高`)
- } else if (bazi.validation.status === 'api_corrected') {
- suggestions.push(`🔍 已使用专业算法修正结果,确保测算准确性`)
- } else {
- suggestions.push(`💡 建议配置专业八字API以获得更准确的测算结果`)
- }
- }
-
- // 根据用神给建议
- const yongshen = bazi.analysis.yongshen.primary
- suggestions.push(`您的用神为${yongshen},建议多接触${yongshen}属性的事物,如颜色、方位、职业等`)
-
- // 根据强弱给建议
- if (bazi.analysis.qiangRuo.type === '身旺') {
- suggestions.push('您的日主偏强,适合发挥领导才能,但要注意不要过于强势')
- } else if (bazi.analysis.qiangRuo.type === '身弱') {
- suggestions.push('您的日主偏弱,需要多寻求他人的帮助和支持,团队合作会更有利')
- } else {
- suggestions.push('您的日主平衡,适合稳步发展,保持现有的良好状态')
- }
-
- return suggestions
- }
- // 导出默认对象
- export default {
- calculateBaZi,
- calculateEnhancedBaZi, // 新增:增强版八字计算
- getBaziFromAPI, // 新增:专业API调用
- analyzeBaziMatch,
- getBaziSuggestions,
- TIANGAN,
- DIZHI,
- TIANGAN_WUXING,
- DIZHI_WUXING,
- SHENGXIAO
- }
|