constellation-match.vue 41 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522
  1. <template>
  2. <view class="constellation-match-page">
  3. <!-- 自定义导航栏 -->
  4. <view class="custom-nav">
  5. <view class="nav-left" @click="goBack">
  6. <text class="back-icon">←</text>
  7. </view>
  8. <view class="nav-title">星座配对</view>
  9. <view class="nav-right"></view>
  10. </view>
  11. <!-- 星座选择区域 -->
  12. <view class="constellation-selection-section" v-if="!hasResult">
  13. <view class="selection-card">
  14. <view class="card-title">💕 星座配对测试</view>
  15. <view class="card-subtitle">看看你们的星座匹配度有多高</view>
  16. <!-- 我的星座选择 -->
  17. <view class="constellation-picker-wrapper">
  18. <view class="picker-label">我的星座</view>
  19. <picker mode="selector" :range="constellationNames" :value="myConstellationIndex" @change="onMyConstellationChange">
  20. <view class="constellation-display">
  21. <text class="constellation-emoji">{{ myConstellationEmoji }}</text>
  22. <text class="constellation-text">{{ myConstellation || '请选择' }}</text>
  23. </view>
  24. </picker>
  25. </view>
  26. <!-- 对方星座选择 -->
  27. <view class="constellation-picker-wrapper">
  28. <view class="picker-label">TA的星座</view>
  29. <picker mode="selector" :range="constellationNames" :value="targetConstellationIndex" @change="onTargetConstellationChange">
  30. <view class="constellation-display">
  31. <text class="constellation-emoji">{{ targetConstellationEmoji }}</text>
  32. <text class="constellation-text">{{ targetConstellation || '请选择' }}</text>
  33. </view>
  34. </picker>
  35. </view>
  36. <button class="submit-btn" @click="handleSubmit" :disabled="!myConstellation || !targetConstellation">
  37. 开始配对
  38. </button>
  39. </view>
  40. <!-- 装饰性星座图标 -->
  41. <view class="constellation-icons">
  42. <text class="constellation-icon" v-for="(constellation, index) in allConstellations" :key="index">
  43. {{ constellation.emoji }}
  44. </text>
  45. </view>
  46. </view>
  47. <!-- 配对结果 -->
  48. <view class="result-section" v-if="hasResult">
  49. <!-- 配对标题卡片 -->
  50. <view class="match-title-card">
  51. <view class="match-header">
  52. <view class="constellation-pair">
  53. <text class="constellation-emoji-large">{{ myConstellationEmoji }}</text>
  54. <text class="vs-text">💕</text>
  55. <text class="constellation-emoji-large">{{ targetConstellationEmoji }}</text>
  56. </view>
  57. <view class="match-title">{{ myConstellation }} 💕 {{ targetConstellation }}</view>
  58. <view class="match-subtitle">{{ matchResult.title || '配对分析' }}</view>
  59. </view>
  60. </view>
  61. <!-- 配对分数 -->
  62. <view class="score-section">
  63. <view class="section-title">💯 配对分数</view>
  64. <view class="score-card">
  65. <view class="score-main">
  66. <view class="score-circle" :style="{background: matchResult.scoreColor}">
  67. <text class="score-number">{{ matchResult.totalScore }}</text>
  68. <text class="score-unit">分</text>
  69. </view>
  70. <view class="score-level" :style="{background: matchResult.levelColor}">
  71. {{ matchResult.level }}
  72. </view>
  73. </view>
  74. <view class="score-breakdown">
  75. <view class="score-item" v-for="(item, index) in matchResult.scoreDetails" :key="index">
  76. <view class="score-item-header">
  77. <text class="score-item-icon">{{ item.icon }}</text>
  78. <text class="score-item-label">{{ item.label }}</text>
  79. </view>
  80. <view class="score-progress">
  81. <view class="progress-bar">
  82. <view class="progress-fill" :style="{width: item.score + '%', background: item.color}"></view>
  83. </view>
  84. <text class="progress-text">{{ item.score }}%</text>
  85. </view>
  86. </view>
  87. </view>
  88. </view>
  89. </view>
  90. <!-- API专业分析 -->
  91. <view class="api-analysis-section" v-if="matchResult.apiGrade || matchResult.apiContent">
  92. <view class="section-title">🎯 专业分析</view>
  93. <view class="api-analysis-card">
  94. <!-- API评级 -->
  95. <view class="api-grade-item" v-if="matchResult.apiGrade">
  96. <view class="grade-header">
  97. <text class="grade-icon">⭐</text>
  98. <text class="grade-title">专业评级</text>
  99. </view>
  100. <text class="grade-content">{{ matchResult.apiGrade }}</text>
  101. </view>
  102. <!-- API详细内容 -->
  103. <view class="api-content-item" v-if="matchResult.apiContent">
  104. <view class="content-header">
  105. <text class="content-icon">📝</text>
  106. <text class="content-title">详细分析</text>
  107. </view>
  108. <text class="content-text">{{ matchResult.apiContent }}</text>
  109. </view>
  110. </view>
  111. </view>
  112. <!-- 配对分析 -->
  113. <view class="match-analysis-section">
  114. <view class="section-title">💝 深度解析</view>
  115. <view class="analysis-card">
  116. <!-- 优势分析 -->
  117. <view class="analysis-item" v-if="matchResult.advantages">
  118. <view class="analysis-header">
  119. <text class="analysis-icon">✨</text>
  120. <text class="analysis-title">配对优势</text>
  121. </view>
  122. <text class="analysis-content">{{ matchResult.advantages }}</text>
  123. </view>
  124. <!-- 挑战分析 -->
  125. <view class="analysis-item" v-if="matchResult.challenges">
  126. <view class="analysis-header">
  127. <text class="analysis-icon">⚠️</text>
  128. <text class="analysis-title">潜在挑战</text>
  129. </view>
  130. <text class="analysis-content">{{ matchResult.challenges }}</text>
  131. </view>
  132. <!-- 建议 -->
  133. <view class="analysis-item" v-if="matchResult.suggestions">
  134. <view class="analysis-header">
  135. <text class="analysis-icon">💡</text>
  136. <text class="analysis-title">相处建议</text>
  137. </view>
  138. <text class="analysis-content">{{ matchResult.suggestions }}</text>
  139. </view>
  140. <!-- 总结 -->
  141. <view class="analysis-item" v-if="matchResult.summary">
  142. <view class="analysis-header">
  143. <text class="analysis-icon">💖</text>
  144. <text class="analysis-title">配对总结</text>
  145. </view>
  146. <text class="analysis-content">{{ matchResult.summary }}</text>
  147. </view>
  148. </view>
  149. </view>
  150. <!-- 元素分析 -->
  151. <view class="element-analysis-section">
  152. <view class="section-title">🔥 元素分析</view>
  153. <view class="element-card">
  154. <view class="element-pair">
  155. <view class="element-item">
  156. <text class="element-name">{{ myConstellationInfo.element }}</text>
  157. <text class="element-desc">{{ getElementDescription(myConstellationInfo.element) }}</text>
  158. </view>
  159. <text class="element-vs">VS</text>
  160. <view class="element-item">
  161. <text class="element-name">{{ targetConstellationInfo.element }}</text>
  162. <text class="element-desc">{{ getElementDescription(targetConstellationInfo.element) }}</text>
  163. </view>
  164. </view>
  165. <view class="element-compatibility">
  166. <text class="compatibility-label">元素相容性</text>
  167. <text class="compatibility-result">{{ matchResult.elementCompatibility }}</text>
  168. </view>
  169. </view>
  170. </view>
  171. <!-- 星座特质对比 -->
  172. <view class="traits-comparison-section">
  173. <view class="section-title">🌟 特质对比</view>
  174. <view class="traits-card">
  175. <view class="traits-comparison">
  176. <view class="traits-column">
  177. <view class="traits-header">
  178. <text class="traits-emoji">{{ myConstellationEmoji }}</text>
  179. <text class="traits-name">{{ myConstellation }}</text>
  180. </view>
  181. <view class="trait-tag" v-for="(trait, index) in myConstellationInfo.traits" :key="index">
  182. {{ trait }}
  183. </view>
  184. </view>
  185. <view class="traits-column">
  186. <view class="traits-header">
  187. <text class="traits-emoji">{{ targetConstellationEmoji }}</text>
  188. <text class="traits-name">{{ targetConstellation }}</text>
  189. </view>
  190. <view class="trait-tag" v-for="(trait, index) in targetConstellationInfo.traits" :key="index">
  191. {{ trait }}
  192. </view>
  193. </view>
  194. </view>
  195. </view>
  196. </view>
  197. <!-- 爱情指数预测 -->
  198. <view class="love-prediction-section">
  199. <view class="section-title">💕 爱情指数预测</view>
  200. <view class="prediction-grid">
  201. <view class="prediction-item" v-for="(item, index) in matchResult.lovePrediction" :key="index">
  202. <view class="prediction-icon-wrapper" :style="{background: item.bgColor}">
  203. <text class="prediction-icon">{{ item.icon }}</text>
  204. </view>
  205. <text class="prediction-label">{{ item.label }}</text>
  206. <text class="prediction-value">{{ item.value }}</text>
  207. </view>
  208. </view>
  209. </view>
  210. <!-- 重新配对 -->
  211. <view class="retest-btn" @click="handleRetest">
  212. 重新配对
  213. </view>
  214. <!-- 数据来源说明 -->
  215. <view class="data-source" :class="{'api-source': matchResult.source === 'tianapi'}">
  216. <text class="source-icon">{{ matchResult.source === 'tianapi' ? '✓' : 'ℹ️' }}</text>
  217. <view class="source-content">
  218. <text class="source-text">数据来源:{{ matchResult.dataFrom || '星座占星学理论' }}</text>
  219. <text class="source-time">更新时间:{{ updateTime }}</text>
  220. </view>
  221. </view>
  222. <!-- 免责声明 -->
  223. <view class="disclaimer">
  224. <view class="disclaimer-title">⚠️ 免责声明</view>
  225. <view class="disclaimer-text">
  226. 本星座配对结果基于传统占星学理论,仅供娱乐参考,不作为感情决策依据。
  227. 真正的爱情需要双方的理解、包容和努力经营。
  228. 每个人都是独特的个体,不要被星座标签所限制。
  229. </view>
  230. </view>
  231. </view>
  232. <!-- 底部占位 -->
  233. <view class="bottom-placeholder"></view>
  234. </view>
  235. </template>
  236. <script>
  237. import constellationUtil from '@/utils/constellation.js'
  238. export default {
  239. data() {
  240. return {
  241. // 星座配对相关数据
  242. myConstellation: '',
  243. targetConstellation: '',
  244. myConstellationIndex: -1,
  245. targetConstellationIndex: -1,
  246. hasResult: false,
  247. matchResult: null,
  248. updateTime: '',
  249. // 星座信息
  250. myConstellationInfo: null,
  251. targetConstellationInfo: null,
  252. // 所有星座数据
  253. allConstellations: constellationUtil.getAllConstellations(),
  254. // 星座名称列表
  255. constellationNames: constellationUtil.getAllConstellations().map(c => c.name)
  256. }
  257. },
  258. computed: {
  259. // 我的星座emoji
  260. myConstellationEmoji() {
  261. return this.myConstellation ? constellationUtil.getConstellationEmoji(this.myConstellation) : '🔮'
  262. },
  263. // 对方星座emoji
  264. targetConstellationEmoji() {
  265. return this.targetConstellation ? constellationUtil.getConstellationEmoji(this.targetConstellation) : '🔮'
  266. }
  267. },
  268. onLoad() {
  269. this.initData()
  270. },
  271. methods: {
  272. initData() {
  273. // 设置更新时间
  274. const date = new Date()
  275. const year = date.getFullYear()
  276. const month = parseInt(date.getMonth() + 1)
  277. const day = parseInt(date.getDate())
  278. this.updateTime = `${year}年${month}月${day}日`
  279. },
  280. // 我的星座选择
  281. onMyConstellationChange(e) {
  282. const index = e.detail.value
  283. this.myConstellationIndex = index
  284. this.myConstellation = this.constellationNames[index]
  285. this.myConstellationInfo = constellationUtil.getConstellationInfo(this.myConstellation)
  286. },
  287. // 对方星座选择
  288. onTargetConstellationChange(e) {
  289. const index = e.detail.value
  290. this.targetConstellationIndex = index
  291. this.targetConstellation = this.constellationNames[index]
  292. this.targetConstellationInfo = constellationUtil.getConstellationInfo(this.targetConstellation)
  293. },
  294. // 提交配对
  295. async handleSubmit() {
  296. if (!this.myConstellation || !this.targetConstellation) {
  297. uni.showToast({
  298. title: '请选择双方星座',
  299. icon: 'none'
  300. })
  301. return
  302. }
  303. // 显示加载中
  304. uni.showLoading({
  305. title: '配对分析中...',
  306. mask: true
  307. })
  308. try {
  309. // 生成配对结果
  310. this.matchResult = await this.generateMatchResult()
  311. this.hasResult = true
  312. // 保存到本地存储
  313. uni.setStorageSync('constellationMatch', {
  314. myConstellation: this.myConstellation,
  315. targetConstellation: this.targetConstellation,
  316. result: this.matchResult,
  317. lastUpdate: new Date().getTime()
  318. })
  319. } catch (error) {
  320. uni.showToast({
  321. title: '分析异常,请重试',
  322. icon: 'none',
  323. duration: 2000
  324. })
  325. } finally {
  326. uni.hideLoading()
  327. }
  328. },
  329. // 生成配对结果
  330. async generateMatchResult() {
  331. try {
  332. // 调用星座配对API(优先API,失败时使用本地数据)
  333. const matchData = await constellationUtil.getDetailedConstellationMatch(
  334. this.myConstellation,
  335. this.targetConstellation
  336. )
  337. if (!matchData) {
  338. throw new Error('获取配对数据失败')
  339. }
  340. // 生成评分详情
  341. const scoreDetails = this.generateScoreDetails(matchData.totalScore)
  342. // 生成总结
  343. const summary = this.generateMatchSummary(matchData)
  344. return {
  345. title: matchData.title || `${this.myConstellation} × ${this.targetConstellation}`,
  346. totalScore: matchData.totalScore,
  347. level: matchData.level,
  348. levelColor: matchData.levelColor,
  349. scoreColor: matchData.scoreColor,
  350. scoreDetails: scoreDetails,
  351. advantages: matchData.advantages,
  352. challenges: matchData.challenges,
  353. suggestions: matchData.suggestions,
  354. summary: summary,
  355. elementCompatibility: matchData.elementCompatibility,
  356. lovePrediction: matchData.lovePrediction,
  357. // API特有数据
  358. apiGrade: matchData.apiGrade || '',
  359. apiContent: matchData.apiContent || '',
  360. source: matchData.source,
  361. dataFrom: matchData.dataFrom
  362. }
  363. } catch (error) {
  364. // 异常时使用本地算法
  365. return this.generateLocalMatchResult()
  366. }
  367. },
  368. // 生成本地配对结果(备用方案)
  369. generateLocalMatchResult() {
  370. const myInfo = this.myConstellationInfo
  371. const targetInfo = this.targetConstellationInfo
  372. // 计算基础匹配度
  373. const baseScore = this.calculateBaseScore(myInfo, targetInfo)
  374. // 生成详细分析
  375. const analysis = this.generateDetailedAnalysis(myInfo, targetInfo, baseScore)
  376. return {
  377. title: `${this.myConstellation} × ${this.targetConstellation}`,
  378. totalScore: baseScore.total,
  379. level: baseScore.level,
  380. levelColor: baseScore.levelColor,
  381. scoreColor: baseScore.scoreColor,
  382. scoreDetails: baseScore.details,
  383. advantages: analysis.advantages,
  384. challenges: analysis.challenges,
  385. suggestions: analysis.suggestions,
  386. summary: analysis.summary,
  387. elementCompatibility: analysis.elementCompatibility,
  388. lovePrediction: analysis.lovePrediction,
  389. apiGrade: '',
  390. apiContent: '',
  391. source: 'local',
  392. dataFrom: '星座占星学理论'
  393. }
  394. },
  395. // 生成评分详情
  396. generateScoreDetails(totalScore) {
  397. return [
  398. {
  399. label: '情感默契',
  400. icon: '💕',
  401. score: Math.min(totalScore + Math.floor(Math.random() * 10) - 5, 100),
  402. color: 'linear-gradient(135deg, #E91E63 0%, #FF6B9D 100%)'
  403. },
  404. {
  405. label: '性格互补',
  406. icon: '🤝',
  407. score: Math.min(totalScore + Math.floor(Math.random() * 8) - 4, 100),
  408. color: 'linear-gradient(135deg, #2196F3 0%, #64B5F6 100%)'
  409. },
  410. {
  411. label: '沟通理解',
  412. icon: '💬',
  413. score: Math.min(totalScore + Math.floor(Math.random() * 12) - 6, 100),
  414. color: 'linear-gradient(135deg, #4CAF50 0%, #81C784 100%)'
  415. },
  416. {
  417. label: '长期发展',
  418. icon: '🌱',
  419. score: Math.min(totalScore + Math.floor(Math.random() * 6) - 3, 100),
  420. color: 'linear-gradient(135deg, #9C27B0 0%, #CE93D8 100%)'
  421. }
  422. ]
  423. },
  424. // 生成配对总结
  425. generateMatchSummary(matchData) {
  426. const totalScore = matchData.totalScore
  427. const constellation1 = this.myConstellation
  428. const constellation2 = this.targetConstellation
  429. // 如果有API内容,优先使用
  430. if (matchData.apiContent) {
  431. return matchData.apiContent
  432. }
  433. // 否则使用本地生成的总结
  434. if (totalScore >= 90) {
  435. return `${constellation1}与${constellation2}的组合堪称天作之合,你们在各个方面都有着很好的默契,是令人羡慕的一对。只要继续保持这份美好,未来充满无限可能。`
  436. } else if (totalScore >= 80) {
  437. return `${constellation1}与${constellation2}是非常匹配的组合,你们能够互相理解和支持。虽然偶尔会有小摩擦,但总体来说是和谐美好的一对。`
  438. } else if (totalScore >= 70) {
  439. return `${constellation1}与${constellation2}的组合比较合适,需要双方多一些耐心和理解。通过磨合和沟通,你们能够建立稳定的关系。`
  440. } else if (totalScore >= 60) {
  441. return `${constellation1}与${constellation2}的组合需要更多努力,但这并不意味着不可能。只要双方都愿意为这份感情付出,就能克服困难。`
  442. } else {
  443. return `${constellation1}与${constellation2}的组合面临较大挑战,需要极大的包容和理解。不过,真爱面前没有不可能,关键在于是否愿意为对方改变。`
  444. }
  445. },
  446. // 计算基础匹配分数
  447. calculateBaseScore(myInfo, targetInfo) {
  448. // 元素相容性得分
  449. const elementScore = this.getElementCompatibilityScore(myInfo.element, targetInfo.element)
  450. // 性格互补性得分
  451. const personalityScore = this.getPersonalityCompatibilityScore(myInfo, targetInfo)
  452. // 传统匹配度得分
  453. const traditionalScore = this.getTraditionalCompatibilityScore(myInfo.name, targetInfo.name)
  454. // 综合计算
  455. const total = Math.round((elementScore * 0.3 + personalityScore * 0.4 + traditionalScore * 0.3))
  456. // 确定等级和颜色
  457. let level, levelColor, scoreColor
  458. if (total >= 90) {
  459. level = '天作之合'
  460. levelColor = 'linear-gradient(135deg, #FF6B9D 0%, #FFA5C6 100%)'
  461. scoreColor = 'linear-gradient(135deg, #FF6B9D 0%, #FFA5C6 100%)'
  462. } else if (total >= 80) {
  463. level = '非常匹配'
  464. levelColor = 'linear-gradient(135deg, #4CAF50 0%, #81C784 100%)'
  465. scoreColor = 'linear-gradient(135deg, #4CAF50 0%, #81C784 100%)'
  466. } else if (total >= 70) {
  467. level = '比较合适'
  468. levelColor = 'linear-gradient(135deg, #2196F3 0%, #64B5F6 100%)'
  469. scoreColor = 'linear-gradient(135deg, #2196F3 0%, #64B5F6 100%)'
  470. } else if (total >= 60) {
  471. level = '需要努力'
  472. levelColor = 'linear-gradient(135deg, #FF9800 0%, #FFB74D 100%)'
  473. scoreColor = 'linear-gradient(135deg, #FF9800 0%, #FFB74D 100%)'
  474. } else {
  475. level = '挑战较大'
  476. levelColor = 'linear-gradient(135deg, #9E9E9E 0%, #BDBDBD 100%)'
  477. scoreColor = 'linear-gradient(135deg, #9E9E9E 0%, #BDBDBD 100%)'
  478. }
  479. return {
  480. total: total,
  481. level: level,
  482. levelColor: levelColor,
  483. scoreColor: scoreColor,
  484. details: [
  485. {
  486. label: '情感默契',
  487. icon: '💕',
  488. score: Math.min(elementScore + 10, 100),
  489. color: 'linear-gradient(135deg, #E91E63 0%, #FF6B9D 100%)'
  490. },
  491. {
  492. label: '性格互补',
  493. icon: '🤝',
  494. score: personalityScore,
  495. color: 'linear-gradient(135deg, #2196F3 0%, #64B5F6 100%)'
  496. },
  497. {
  498. label: '沟通理解',
  499. icon: '💬',
  500. score: Math.min(traditionalScore + 5, 100),
  501. color: 'linear-gradient(135deg, #4CAF50 0%, #81C784 100%)'
  502. },
  503. {
  504. label: '长期发展',
  505. icon: '🌱',
  506. score: Math.min(total - 5, 100),
  507. color: 'linear-gradient(135deg, #9C27B0 0%, #CE93D8 100%)'
  508. }
  509. ]
  510. }
  511. },
  512. // 获取元素相容性得分
  513. getElementCompatibilityScore(element1, element2) {
  514. const compatibilityMatrix = {
  515. '火象': { '火象': 85, '土象': 65, '风象': 90, '水象': 45 },
  516. '土象': { '火象': 65, '土象': 80, '风象': 55, '水象': 95 },
  517. '风象': { '火象': 90, '土象': 55, '风象': 75, '水象': 70 },
  518. '水象': { '火象': 45, '土象': 95, '风象': 70, '水象': 85 }
  519. }
  520. return compatibilityMatrix[element1]?.[element2] || 70
  521. },
  522. // 获取性格相容性得分
  523. getPersonalityCompatibilityScore(myInfo, targetInfo) {
  524. // 基于传统星座配对理论的得分
  525. const isInBestList = myInfo.compatibility.best.includes(targetInfo.name)
  526. const isInGoodList = myInfo.compatibility.good.includes(targetInfo.name)
  527. const isInAvoidList = myInfo.compatibility.avoid.includes(targetInfo.name)
  528. if (isInBestList) return 95
  529. if (isInGoodList) return 80
  530. if (isInAvoidList) return 50
  531. return 70 // 中性匹配
  532. },
  533. // 获取传统配对得分
  534. getTraditionalCompatibilityScore(constellation1, constellation2) {
  535. // 反向查找,确保双向匹配
  536. const info1 = constellationUtil.getConstellationInfo(constellation1)
  537. const info2 = constellationUtil.getConstellationInfo(constellation2)
  538. let score1 = 70, score2 = 70
  539. if (info1.compatibility.best.includes(constellation2)) score1 = 95
  540. else if (info1.compatibility.good.includes(constellation2)) score1 = 80
  541. else if (info1.compatibility.avoid.includes(constellation2)) score1 = 50
  542. if (info2.compatibility.best.includes(constellation1)) score2 = 95
  543. else if (info2.compatibility.good.includes(constellation1)) score2 = 80
  544. else if (info2.compatibility.avoid.includes(constellation1)) score2 = 50
  545. return Math.round((score1 + score2) / 2)
  546. },
  547. // 生成详细分析
  548. generateDetailedAnalysis(myInfo, targetInfo, baseScore) {
  549. const myElement = myInfo.element
  550. const targetElement = targetInfo.element
  551. const totalScore = baseScore.total
  552. // 生成优势分析
  553. const advantages = this.generateAdvantages(myInfo, targetInfo, myElement, targetElement)
  554. // 生成挑战分析
  555. const challenges = this.generateChallenges(myInfo, targetInfo, myElement, targetElement)
  556. // 生成建议
  557. const suggestions = this.generateSuggestions(myInfo, targetInfo, totalScore)
  558. // 生成总结
  559. const summary = this.generateSummary(myInfo, targetInfo, totalScore)
  560. // 元素相容性描述
  561. const elementCompatibility = this.getElementCompatibilityDescription(myElement, targetElement)
  562. // 爱情指数预测
  563. const lovePrediction = this.generateLovePrediction(myInfo, targetInfo, totalScore)
  564. return {
  565. advantages,
  566. challenges,
  567. suggestions,
  568. summary,
  569. elementCompatibility,
  570. lovePrediction
  571. }
  572. },
  573. // 生成优势分析
  574. generateAdvantages(myInfo, targetInfo, myElement, targetElement) {
  575. const advantages = []
  576. // 基于元素的优势
  577. if (myElement === targetElement) {
  578. advantages.push('你们属于同一元素,有着相似的价值观和生活节奏')
  579. } else if (
  580. (myElement === '火象' && targetElement === '风象') ||
  581. (myElement === '风象' && targetElement === '火象')
  582. ) {
  583. advantages.push('火象与风象的组合充满激情与创意,能够互相激发潜能')
  584. } else if (
  585. (myElement === '土象' && targetElement === '水象') ||
  586. (myElement === '水象' && targetElement === '土象')
  587. ) {
  588. advantages.push('土象与水象的结合稳定而温馨,能够建立深厚的情感基础')
  589. }
  590. // 基于性格特质的优势
  591. const commonTraits = myInfo.traits.filter(trait => targetInfo.traits.includes(trait))
  592. if (commonTraits.length > 0) {
  593. advantages.push(`你们都具有${commonTraits.join('、')}的特质,容易产生共鸣`)
  594. }
  595. // 基于星座特性的优势
  596. if (myInfo.compatibility.best.includes(targetInfo.name)) {
  597. advantages.push('从传统占星学角度来看,你们是非常理想的配对组合')
  598. }
  599. return advantages.join(';') || '你们的组合有着独特的魅力,能够在相处中发现彼此的闪光点。'
  600. },
  601. // 生成挑战分析
  602. generateChallenges(myInfo, targetInfo, myElement, targetElement) {
  603. const challenges = []
  604. // 基于元素的挑战
  605. if (
  606. (myElement === '火象' && targetElement === '水象') ||
  607. (myElement === '水象' && targetElement === '火象')
  608. ) {
  609. challenges.push('火象与水象的组合可能在表达方式上存在差异,需要更多理解')
  610. } else if (
  611. (myElement === '土象' && targetElement === '风象') ||
  612. (myElement === '风象' && targetElement === '土象')
  613. ) {
  614. challenges.push('土象的稳重与风象的多变可能产生摩擦,需要找到平衡点')
  615. }
  616. // 基于避免列表的挑战
  617. if (myInfo.compatibility.avoid.includes(targetInfo.name)) {
  618. challenges.push('你们的性格差异较大,需要更多的耐心和包容来磨合')
  619. }
  620. // 通用挑战
  621. challenges.push('任何关系都需要双方的努力和妥协,保持开放的沟通很重要')
  622. return challenges.join(';')
  623. },
  624. // 生成建议
  625. generateSuggestions(myInfo, targetInfo, totalScore) {
  626. const suggestions = []
  627. if (totalScore >= 80) {
  628. suggestions.push('你们的匹配度很高,要珍惜这份缘分,在相处中保持真诚和理解')
  629. } else if (totalScore >= 60) {
  630. suggestions.push('通过增进了解和有效沟通,你们的关系会更加稳固')
  631. } else {
  632. suggestions.push('虽然挑战较大,但只要双方都愿意努力,任何困难都可以克服')
  633. }
  634. // 基于星座特性的建议
  635. suggestions.push(`理解${myInfo.name}的${myInfo.personality}和${targetInfo.name}的${targetInfo.personality},互相欣赏对方的独特之处`)
  636. suggestions.push('记住,星座只是参考,真正的爱情需要用心经营')
  637. return suggestions.join(';')
  638. },
  639. // 生成总结
  640. generateSummary(myInfo, targetInfo, totalScore) {
  641. if (totalScore >= 90) {
  642. return `${myInfo.name}与${targetInfo.name}的组合堪称天作之合,你们在各个方面都有着很好的默契,是令人羡慕的一对。只要继续保持这份美好,未来充满无限可能。`
  643. } else if (totalScore >= 80) {
  644. return `${myInfo.name}与${targetInfo.name}是非常匹配的组合,你们能够互相理解和支持。虽然偶尔会有小摩擦,但总体来说是和谐美好的一对。`
  645. } else if (totalScore >= 70) {
  646. return `${myInfo.name}与${targetInfo.name}的组合比较合适,需要双方多一些耐心和理解。通过磨合和沟通,你们能够建立稳定的关系。`
  647. } else if (totalScore >= 60) {
  648. return `${myInfo.name}与${targetInfo.name}的组合需要更多努力,但这并不意味着不可能。只要双方都愿意为这份感情付出,就能克服困难。`
  649. } else {
  650. return `${myInfo.name}与${targetInfo.name}的组合面临较大挑战,需要极大的包容和理解。不过,真爱面前没有不可能,关键在于是否愿意为对方改变。`
  651. }
  652. },
  653. // 获取元素相容性描述
  654. getElementCompatibilityDescription(element1, element2) {
  655. const descriptions = {
  656. '火象火象': '同为火象星座,你们都充满激情和活力,能够互相理解对方的冲动和热情',
  657. '火象土象': '火象的激情与土象的稳重形成互补,但需要找到节奏的平衡点',
  658. '火象风象': '火象与风象的结合如同火遇风,能够互相激发,创造出更大的能量',
  659. '火象水象': '火象与水象的组合对比强烈,需要更多的理解和包容',
  660. '土象土象': '同为土象星座,你们都追求稳定和安全感,能够建立坚实的关系基础',
  661. '土象风象': '土象的踏实与风象的灵活可能产生分歧,需要相互学习和适应',
  662. '土象水象': '土象与水象的组合非常和谐,既有稳定性又有情感深度',
  663. '风象风象': '同为风象星座,你们都重视精神交流,思维活跃,有很多共同话题',
  664. '风象水象': '风象的理性与水象的感性形成有趣的对比,能够互相学习',
  665. '水象水象': '同为水象星座,你们情感丰富,能够深度理解彼此的内心世界'
  666. }
  667. const key = element1 + element2
  668. return descriptions[key] || descriptions[element2 + element1] || '你们的元素组合有着独特的化学反应'
  669. },
  670. // 生成爱情指数预测
  671. generateLovePrediction(myInfo, targetInfo, totalScore) {
  672. const baseScore = totalScore
  673. return [
  674. {
  675. label: '初见印象',
  676. icon: '👀',
  677. value: Math.min(baseScore + Math.floor(Math.random() * 10) - 5, 100) + '%',
  678. bgColor: 'linear-gradient(135deg, #FFB6C1 0%, #FFE4E1 100%)'
  679. },
  680. {
  681. label: '恋爱甜蜜度',
  682. icon: '🍯',
  683. value: Math.min(baseScore + Math.floor(Math.random() * 15) - 7, 100) + '%',
  684. bgColor: 'linear-gradient(135deg, #FF6B9D 0%, #FFA5C6 100%)'
  685. },
  686. {
  687. label: '长期稳定性',
  688. icon: '🏠',
  689. value: Math.min(baseScore + Math.floor(Math.random() * 8) - 4, 100) + '%',
  690. bgColor: 'linear-gradient(135deg, #4CAF50 0%, #81C784 100%)'
  691. },
  692. {
  693. label: '婚姻契合度',
  694. icon: '💍',
  695. value: Math.min(baseScore + Math.floor(Math.random() * 12) - 6, 100) + '%',
  696. bgColor: 'linear-gradient(135deg, #9C27B0 0%, #CE93D8 100%)'
  697. }
  698. ]
  699. },
  700. // 获取元素描述
  701. getElementDescription(element) {
  702. const descriptions = {
  703. '火象': '热情、积极、冲动',
  704. '土象': '稳重、务实、踏实',
  705. '风象': '理智、灵活、善变',
  706. '水象': '感性、直觉、温柔'
  707. }
  708. return descriptions[element] || element
  709. },
  710. // 重新配对
  711. handleRetest() {
  712. this.hasResult = false
  713. this.myConstellation = ''
  714. this.targetConstellation = ''
  715. this.myConstellationIndex = -1
  716. this.targetConstellationIndex = -1
  717. this.matchResult = null
  718. this.myConstellationInfo = null
  719. this.targetConstellationInfo = null
  720. },
  721. // 返回
  722. goBack() {
  723. uni.navigateBack({
  724. delta: 1
  725. })
  726. }
  727. }
  728. }
  729. </script>
  730. <style lang="scss" scoped>
  731. .constellation-match-page {
  732. min-height: 100vh;
  733. background: linear-gradient(180deg, #FFF9F9 0%, #FFFFFF 50%);
  734. padding-bottom: 40rpx;
  735. }
  736. /* 自定义导航栏 */
  737. .custom-nav {
  738. position: relative;
  739. display: flex;
  740. align-items: center;
  741. justify-content: space-between;
  742. height: 88rpx;
  743. padding: 0 30rpx;
  744. background-color: #FFFFFF;
  745. border-bottom: 1rpx solid #F0F0F0;
  746. .nav-left {
  747. width: 80rpx;
  748. .back-icon {
  749. font-size: 40rpx;
  750. color: #333333;
  751. }
  752. }
  753. .nav-title {
  754. position: absolute;
  755. left: 50%;
  756. transform: translateX(-50%);
  757. font-size: 34rpx;
  758. font-weight: 600;
  759. color: #333333;
  760. }
  761. .nav-right {
  762. width: 80rpx;
  763. }
  764. }
  765. /* 星座选择区域 */
  766. .constellation-selection-section {
  767. padding: 60rpx 30rpx;
  768. display: flex;
  769. flex-direction: column;
  770. align-items: center;
  771. .selection-card {
  772. width: 100%;
  773. background-color: #FFFFFF;
  774. border-radius: 30rpx;
  775. padding: 60rpx 40rpx;
  776. box-shadow: 0 8rpx 30rpx rgba(233, 30, 99, 0.1);
  777. text-align: center;
  778. .card-title {
  779. font-size: 40rpx;
  780. font-weight: bold;
  781. color: #333333;
  782. margin-bottom: 15rpx;
  783. }
  784. .card-subtitle {
  785. font-size: 26rpx;
  786. color: #999999;
  787. margin-bottom: 50rpx;
  788. }
  789. .constellation-picker-wrapper {
  790. margin-bottom: 30rpx;
  791. text-align: left;
  792. .picker-label {
  793. font-size: 28rpx;
  794. color: #666666;
  795. margin-bottom: 15rpx;
  796. }
  797. .constellation-display {
  798. display: flex;
  799. align-items: center;
  800. justify-content: center;
  801. background-color: #F8F8F8;
  802. border-radius: 20rpx;
  803. padding: 25rpx 30rpx;
  804. border: 2rpx solid #E91E63;
  805. transition: all 0.3s;
  806. .constellation-emoji {
  807. font-size: 40rpx;
  808. margin-right: 15rpx;
  809. }
  810. .constellation-text {
  811. font-size: 32rpx;
  812. color: #333333;
  813. font-weight: 500;
  814. }
  815. }
  816. &:active .constellation-display {
  817. background-color: #FFE5EE;
  818. transform: scale(0.98);
  819. }
  820. }
  821. .submit-btn {
  822. width: 100%;
  823. height: 90rpx;
  824. background: linear-gradient(135deg, #E91E63 0%, #FF6B9D 100%);
  825. color: #FFFFFF;
  826. font-size: 32rpx;
  827. font-weight: 600;
  828. border-radius: 45rpx;
  829. border: none;
  830. box-shadow: 0 8rpx 20rpx rgba(233, 30, 99, 0.3);
  831. &:disabled {
  832. opacity: 0.5;
  833. }
  834. &:active:not(:disabled) {
  835. opacity: 0.9;
  836. }
  837. }
  838. }
  839. .constellation-icons {
  840. display: flex;
  841. flex-wrap: wrap;
  842. justify-content: center;
  843. gap: 20rpx;
  844. margin-top: 50rpx;
  845. opacity: 0.3;
  846. .constellation-icon {
  847. font-size: 48rpx;
  848. animation: float 3s ease-in-out infinite;
  849. &:nth-child(2n) {
  850. animation-delay: 0.5s;
  851. }
  852. &:nth-child(3n) {
  853. animation-delay: 1s;
  854. }
  855. }
  856. }
  857. }
  858. @keyframes float {
  859. 0%, 100% {
  860. transform: translateY(0);
  861. }
  862. 50% {
  863. transform: translateY(-10rpx);
  864. }
  865. }
  866. /* 结果区域 */
  867. .result-section {
  868. padding: 30rpx 25rpx 40rpx 25rpx;
  869. }
  870. /* 配对标题卡片 */
  871. .match-title-card {
  872. background: linear-gradient(135deg, #FF6B9D 0%, #FFA5C6 100%);
  873. border-radius: 32rpx;
  874. padding: 60rpx 40rpx;
  875. text-align: center;
  876. box-shadow: 0 12rpx 40rpx rgba(233, 30, 99, 0.25);
  877. margin-bottom: 40rpx;
  878. .match-header {
  879. text-align: center;
  880. .constellation-pair {
  881. display: flex;
  882. align-items: center;
  883. justify-content: center;
  884. margin-bottom: 30rpx;
  885. .constellation-emoji-large {
  886. font-size: 120rpx;
  887. }
  888. .vs-text {
  889. font-size: 70rpx;
  890. margin: 0 30rpx;
  891. }
  892. }
  893. .match-title {
  894. font-size: 42rpx;
  895. font-weight: bold;
  896. color: #FFFFFF;
  897. margin-bottom: 15rpx;
  898. letter-spacing: 2rpx;
  899. }
  900. .match-subtitle {
  901. font-size: 28rpx;
  902. color: rgba(255, 255, 255, 0.9);
  903. }
  904. }
  905. }
  906. /* 通用标题 */
  907. .section-title {
  908. font-size: 36rpx;
  909. font-weight: 600;
  910. color: #333333;
  911. margin-bottom: 25rpx;
  912. padding: 0 10rpx;
  913. display: flex;
  914. align-items: center;
  915. justify-content: flex-start;
  916. }
  917. /* 配对分数 */
  918. .score-section {
  919. margin-bottom: 40rpx;
  920. .score-card {
  921. background-color: #FFFFFF;
  922. border-radius: 24rpx;
  923. padding: 40rpx 30rpx;
  924. box-shadow: 0 6rpx 24rpx rgba(0, 0, 0, 0.08);
  925. .score-main {
  926. display: flex;
  927. justify-content: space-between;
  928. align-items: center;
  929. margin-bottom: 40rpx;
  930. padding-bottom: 30rpx;
  931. border-bottom: 1rpx solid #F0F0F0;
  932. .score-circle {
  933. width: 150rpx;
  934. height: 150rpx;
  935. border-radius: 50%;
  936. display: flex;
  937. flex-direction: column;
  938. align-items: center;
  939. justify-content: center;
  940. color: #FFFFFF;
  941. .score-number {
  942. font-size: 48rpx;
  943. font-weight: bold;
  944. line-height: 1;
  945. }
  946. .score-unit {
  947. font-size: 24rpx;
  948. margin-top: 5rpx;
  949. }
  950. }
  951. .score-level {
  952. padding: 15rpx 40rpx;
  953. border-radius: 30rpx;
  954. font-size: 32rpx;
  955. color: #FFFFFF;
  956. font-weight: 600;
  957. }
  958. }
  959. .score-breakdown {
  960. .score-item {
  961. margin-bottom: 25rpx;
  962. &:last-child {
  963. margin-bottom: 0;
  964. }
  965. .score-item-header {
  966. display: flex;
  967. align-items: center;
  968. margin-bottom: 12rpx;
  969. .score-item-icon {
  970. font-size: 28rpx;
  971. margin-right: 12rpx;
  972. }
  973. .score-item-label {
  974. font-size: 28rpx;
  975. color: #333333;
  976. font-weight: 500;
  977. }
  978. }
  979. .score-progress {
  980. display: flex;
  981. align-items: center;
  982. .progress-bar {
  983. flex: 1;
  984. height: 12rpx;
  985. background-color: #F0F0F0;
  986. border-radius: 6rpx;
  987. overflow: hidden;
  988. margin-right: 15rpx;
  989. .progress-fill {
  990. height: 100%;
  991. border-radius: 6rpx;
  992. transition: width 0.6s ease;
  993. }
  994. }
  995. .progress-text {
  996. font-size: 24rpx;
  997. color: #E91E63;
  998. font-weight: 600;
  999. min-width: 60rpx;
  1000. text-align: right;
  1001. }
  1002. }
  1003. }
  1004. }
  1005. }
  1006. }
  1007. /* API专业分析 */
  1008. .api-analysis-section {
  1009. margin-bottom: 40rpx;
  1010. .api-analysis-card {
  1011. background: linear-gradient(135deg, #E8F5E9 0%, #F1F8E9 100%);
  1012. border-radius: 24rpx;
  1013. padding: 0;
  1014. box-shadow: 0 6rpx 24rpx rgba(76, 175, 80, 0.15);
  1015. overflow: hidden;
  1016. border-left: 6rpx solid #4CAF50;
  1017. .api-grade-item, .api-content-item {
  1018. padding: 30rpx;
  1019. border-bottom: 1rpx solid rgba(76, 175, 80, 0.1);
  1020. &:last-child {
  1021. border-bottom: none;
  1022. }
  1023. .grade-header, .content-header {
  1024. display: flex;
  1025. align-items: center;
  1026. margin-bottom: 15rpx;
  1027. .grade-icon, .content-icon {
  1028. font-size: 32rpx;
  1029. margin-right: 15rpx;
  1030. }
  1031. .grade-title, .content-title {
  1032. font-size: 30rpx;
  1033. color: #2E7D32;
  1034. font-weight: 600;
  1035. }
  1036. }
  1037. .grade-content, .content-text {
  1038. font-size: 28rpx;
  1039. color: #333333;
  1040. line-height: 1.8;
  1041. text-align: justify;
  1042. margin-left: 47rpx;
  1043. }
  1044. .grade-content {
  1045. color: #4CAF50;
  1046. font-weight: 500;
  1047. }
  1048. }
  1049. }
  1050. }
  1051. /* 配对分析 */
  1052. .match-analysis-section {
  1053. margin-bottom: 40rpx;
  1054. .analysis-card {
  1055. background-color: #FFFFFF;
  1056. border-radius: 24rpx;
  1057. padding: 0;
  1058. box-shadow: 0 6rpx 24rpx rgba(0, 0, 0, 0.08);
  1059. overflow: hidden;
  1060. .analysis-item {
  1061. padding: 30rpx;
  1062. border-bottom: 1rpx solid #F5F5F5;
  1063. &:last-child {
  1064. border-bottom: none;
  1065. }
  1066. .analysis-header {
  1067. display: flex;
  1068. align-items: center;
  1069. margin-bottom: 15rpx;
  1070. .analysis-icon {
  1071. font-size: 32rpx;
  1072. margin-right: 15rpx;
  1073. }
  1074. .analysis-title {
  1075. font-size: 30rpx;
  1076. color: #E91E63;
  1077. font-weight: 600;
  1078. }
  1079. }
  1080. .analysis-content {
  1081. font-size: 28rpx;
  1082. color: #333333;
  1083. line-height: 1.8;
  1084. text-align: justify;
  1085. margin-left: 47rpx;
  1086. }
  1087. }
  1088. }
  1089. }
  1090. /* 元素分析 */
  1091. .element-analysis-section {
  1092. margin-bottom: 40rpx;
  1093. .element-card {
  1094. background-color: #FFFFFF;
  1095. border-radius: 24rpx;
  1096. padding: 40rpx 30rpx;
  1097. box-shadow: 0 6rpx 24rpx rgba(0, 0, 0, 0.08);
  1098. .element-pair {
  1099. display: flex;
  1100. align-items: center;
  1101. justify-content: space-between;
  1102. margin-bottom: 30rpx;
  1103. .element-item {
  1104. flex: 1;
  1105. text-align: center;
  1106. .element-name {
  1107. display: block;
  1108. font-size: 32rpx;
  1109. color: #E91E63;
  1110. font-weight: 600;
  1111. margin-bottom: 10rpx;
  1112. }
  1113. .element-desc {
  1114. font-size: 24rpx;
  1115. color: #666666;
  1116. }
  1117. }
  1118. .element-vs {
  1119. font-size: 28rpx;
  1120. color: #999999;
  1121. font-weight: 600;
  1122. margin: 0 20rpx;
  1123. }
  1124. }
  1125. .element-compatibility {
  1126. background: linear-gradient(135deg, #F3E5F5 0%, #FFEEF5 100%);
  1127. border-radius: 15rpx;
  1128. padding: 25rpx;
  1129. text-align: center;
  1130. .compatibility-label {
  1131. display: block;
  1132. font-size: 24rpx;
  1133. color: #9C27B0;
  1134. margin-bottom: 10rpx;
  1135. }
  1136. .compatibility-result {
  1137. font-size: 28rpx;
  1138. color: #333333;
  1139. line-height: 1.6;
  1140. }
  1141. }
  1142. }
  1143. }
  1144. /* 特质对比 */
  1145. .traits-comparison-section {
  1146. margin-bottom: 40rpx;
  1147. .traits-card {
  1148. background-color: #FFFFFF;
  1149. border-radius: 24rpx;
  1150. padding: 40rpx 30rpx;
  1151. box-shadow: 0 6rpx 24rpx rgba(0, 0, 0, 0.08);
  1152. .traits-comparison {
  1153. display: flex;
  1154. gap: 30rpx;
  1155. .traits-column {
  1156. flex: 1;
  1157. .traits-header {
  1158. display: flex;
  1159. align-items: center;
  1160. justify-content: center;
  1161. margin-bottom: 20rpx;
  1162. .traits-emoji {
  1163. font-size: 40rpx;
  1164. margin-right: 10rpx;
  1165. }
  1166. .traits-name {
  1167. font-size: 28rpx;
  1168. color: #333333;
  1169. font-weight: 600;
  1170. }
  1171. }
  1172. .trait-tag {
  1173. display: inline-block;
  1174. background: linear-gradient(135deg, #E3F2FD 0%, #F0F8FF 100%);
  1175. color: #2196F3;
  1176. font-size: 22rpx;
  1177. padding: 8rpx 16rpx;
  1178. border-radius: 20rpx;
  1179. margin: 5rpx;
  1180. border: 1rpx solid #2196F3;
  1181. }
  1182. }
  1183. }
  1184. }
  1185. }
  1186. /* 爱情指数预测 */
  1187. .love-prediction-section {
  1188. margin-bottom: 40rpx;
  1189. .prediction-grid {
  1190. display: grid;
  1191. grid-template-columns: repeat(2, 1fr);
  1192. gap: 20rpx;
  1193. .prediction-item {
  1194. display: flex;
  1195. flex-direction: column;
  1196. align-items: center;
  1197. background-color: #FFFFFF;
  1198. border-radius: 15rpx;
  1199. padding: 30rpx 20rpx;
  1200. box-shadow: 0 4rpx 12rpx rgba(0, 0, 0, 0.06);
  1201. .prediction-icon-wrapper {
  1202. width: 80rpx;
  1203. height: 80rpx;
  1204. border-radius: 50%;
  1205. display: flex;
  1206. align-items: center;
  1207. justify-content: center;
  1208. margin-bottom: 15rpx;
  1209. .prediction-icon {
  1210. font-size: 40rpx;
  1211. }
  1212. }
  1213. .prediction-label {
  1214. font-size: 24rpx;
  1215. color: #999999;
  1216. margin-bottom: 8rpx;
  1217. }
  1218. .prediction-value {
  1219. font-size: 28rpx;
  1220. color: #333333;
  1221. font-weight: 600;
  1222. }
  1223. }
  1224. }
  1225. }
  1226. /* 重新配对 */
  1227. .retest-btn {
  1228. text-align: center;
  1229. padding: 30rpx 40rpx;
  1230. font-size: 30rpx;
  1231. color: #666666;
  1232. background-color: #F8F8F8;
  1233. border-radius: 25rpx;
  1234. margin: 20rpx 20rpx 30rpx 20rpx;
  1235. border: 2rpx solid #E0E0E0;
  1236. &:active {
  1237. color: #E91E63;
  1238. background-color: #FFF0F5;
  1239. border-color: #E91E63;
  1240. }
  1241. }
  1242. /* 数据来源说明 */
  1243. .data-source {
  1244. display: flex;
  1245. align-items: center;
  1246. background-color: #E3F2FD;
  1247. border-radius: 20rpx;
  1248. padding: 25rpx 30rpx;
  1249. margin-bottom: 30rpx;
  1250. transition: all 0.3s;
  1251. .source-icon {
  1252. font-size: 32rpx;
  1253. margin-right: 15rpx;
  1254. }
  1255. .source-content {
  1256. flex: 1;
  1257. display: flex;
  1258. flex-direction: column;
  1259. gap: 8rpx;
  1260. .source-text {
  1261. font-size: 28rpx;
  1262. color: #1976D2;
  1263. font-weight: 500;
  1264. }
  1265. .source-time {
  1266. font-size: 24rpx;
  1267. color: #64B5F6;
  1268. }
  1269. }
  1270. // API数据特殊样式
  1271. &.api-source {
  1272. background: linear-gradient(135deg, #E8F5E9 0%, #C8E6C9 100%);
  1273. border-left: 6rpx solid #4CAF50;
  1274. .source-icon {
  1275. color: #4CAF50;
  1276. }
  1277. .source-text {
  1278. color: #2E7D32;
  1279. }
  1280. .source-time {
  1281. color: #66BB6A;
  1282. }
  1283. }
  1284. }
  1285. /* 免责声明 */
  1286. .disclaimer {
  1287. background-color: #FFF3E0;
  1288. border-radius: 20rpx;
  1289. padding: 30rpx;
  1290. border-left: 6rpx solid #FF9800;
  1291. margin: 0 10rpx;
  1292. .disclaimer-title {
  1293. font-size: 30rpx;
  1294. font-weight: 600;
  1295. color: #F57C00;
  1296. margin-bottom: 20rpx;
  1297. }
  1298. .disclaimer-text {
  1299. font-size: 26rpx;
  1300. color: #666666;
  1301. line-height: 2.0;
  1302. text-align: justify;
  1303. }
  1304. }
  1305. /* 底部占位 */
  1306. .bottom-placeholder {
  1307. height: 60rpx;
  1308. }
  1309. </style>