zodiac-enhanced.js 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518
  1. /**
  2. * 增强版生肖工具 - 接入天行数据API
  3. */
  4. import TIANAPI_CONFIG, { validateConfig } from '@/config/api-config.js'
  5. import zodiacUtil from './zodiac.js'
  6. /**
  7. * 从天行数据API获取生肖运势
  8. * @param {String} zodiac - 生肖名称
  9. * @returns {Promise<Object>} 运势数据
  10. */
  11. export async function getZodiacFortuneFromAPI(zodiac) {
  12. // ⚠️ 注意:天行数据的 /zodiac/index 是生肖配对接口,不是运势接口
  13. // 该接口需要 me 和 he 两个参数,用于查询生肖配对关系
  14. // 目前天行数据可能没有单独的生肖运势接口,因此直接使用本地数据
  15. console.log('ℹ️ 天行数据暂无生肖运势接口,使用本地数据')
  16. console.log('📝 说明: /zodiac/index 是生肖配对接口,不是运势接口')
  17. // 直接返回本地数据
  18. return {
  19. ...zodiacUtil.getTodayFortune(zodiac),
  20. source: 'local_no_api',
  21. dataFrom: '本地数据(天行数据暂无运势接口)',
  22. updateTime: new Date().toLocaleString('zh-CN')
  23. }
  24. /*
  25. // 保留代码供参考:如果找到正确的运势API,可以恢复使用
  26. // 验证配置
  27. if (!validateConfig()) {
  28. console.log('API Key未配置,使用本地数据')
  29. return {
  30. ...zodiacUtil.getTodayFortune(zodiac),
  31. source: 'local_no_config',
  32. dataFrom: '本地数据(未配置API)'
  33. }
  34. }
  35. try {
  36. console.log('🔍 开始调用天行数据API...')
  37. console.log('请求生肖:', zodiac)
  38. // 调用天行数据API(使用Promise包装以捕获所有错误)
  39. const [error, response] = await uni.request({
  40. url: `${TIANAPI_CONFIG.BASE_URL}${TIANAPI_CONFIG.ENDPOINTS.zodiacFortune}`,
  41. method: 'GET',
  42. data: {
  43. key: TIANAPI_CONFIG.API_KEY,
  44. name: zodiac
  45. },
  46. timeout: 8000 // 8秒超时,给网络更多时间
  47. }).then(res => [null, res]).catch(err => [err, null])
  48. // 如果请求本身失败(网络错误等)
  49. if (error) {
  50. console.error('❌ 网络请求失败:', error)
  51. throw new Error(`网络错误: ${error.errMsg || error.message || '未知错误'}`)
  52. }
  53. console.log('📡 API响应状态码:', response.statusCode)
  54. console.log('📡 API响应数据:', response.data)
  55. // 检查HTTP响应状态
  56. if (!response || response.statusCode !== 200) {
  57. console.error('❌ HTTP状态码异常:', response?.statusCode)
  58. throw new Error(`HTTP错误: ${response?.statusCode || '无响应'}`)
  59. }
  60. const data = response.data
  61. // 检查数据格式
  62. if (!data || typeof data !== 'object') {
  63. console.error('❌ 响应数据格式错误:', data)
  64. throw new Error('响应数据格式不正确')
  65. }
  66. // 检查API业务状态码
  67. if (data.code !== 200) {
  68. console.error('❌ API业务错误:', {
  69. code: data.code,
  70. msg: data.msg
  71. })
  72. throw new Error(data.msg || `API错误(code: ${data.code})`)
  73. }
  74. // 检查result字段
  75. const result = data.result
  76. if (!result) {
  77. console.error('❌ 缺少result数据')
  78. throw new Error('API返回数据不完整')
  79. }
  80. console.log('✅ API调用成功,数据:', result)
  81. // 天行数据返回格式转换为我们的格式
  82. return {
  83. overall: result.summary || '平稳',
  84. love: parseFortune(result.love_txt),
  85. career: parseFortune(result.work_txt),
  86. wealth: parseFortune(result.money_txt),
  87. health: parseFortune(result.health_txt),
  88. tips: `幸运颜色:${result.color || '未知'},幸运数字:${result.number || '未知'}。${result.general_txt || ''}`,
  89. luckyColor: result.color || zodiacUtil.getZodiacInfo(zodiac).luckyColor,
  90. luckyNumber: result.number || zodiacUtil.getZodiacInfo(zodiac).luckyNumber,
  91. source: 'tianapi',
  92. dataFrom: '天行数据专业API',
  93. updateTime: new Date().toLocaleString('zh-CN')
  94. }
  95. } catch (error) {
  96. console.error('❌ 获取API数据失败,降级到本地数据')
  97. console.error('错误详情:', error)
  98. console.error('错误消息:', error.message || error.errMsg || '未知错误')
  99. // 显示友好提示(不打断用户)
  100. uni.showToast({
  101. title: '使用本地数据',
  102. icon: 'none',
  103. duration: 1500
  104. })
  105. // 降级到本地数据
  106. return {
  107. ...zodiacUtil.getTodayFortune(zodiac),
  108. source: 'local_fallback',
  109. dataFrom: '本地数据(API暂不可用)',
  110. updateTime: new Date().toLocaleString('zh-CN')
  111. }
  112. }
  113. */
  114. }
  115. /**
  116. * 🆕 生肖配对查询(使用天行数据API)
  117. * @param {String} myZodiac - 我的生肖
  118. * @param {String} targetZodiac - 对方生肖
  119. * @returns {Promise<Object>} 配对结果
  120. */
  121. export async function getZodiacMatch(myZodiac, targetZodiac) {
  122. // 验证配置
  123. if (!validateConfig()) {
  124. console.log('API Key未配置,无法使用配对功能')
  125. return null
  126. }
  127. try {
  128. console.log('🔍 开始调用生肖配对API...')
  129. console.log('我的生肖:', myZodiac, '对方生肖:', targetZodiac)
  130. console.log('请求URL:', `${TIANAPI_CONFIG.BASE_URL}${TIANAPI_CONFIG.ENDPOINTS.zodiacMatch}`)
  131. console.log('请求参数:', {
  132. key: TIANAPI_CONFIG.API_KEY ? TIANAPI_CONFIG.API_KEY.substring(0, 8) + '...' : '未配置',
  133. me: myZodiac,
  134. he: targetZodiac
  135. })
  136. // 使用Promise包装uni.request以更好地处理错误
  137. const response = await new Promise((resolve, reject) => {
  138. uni.request({
  139. url: `${TIANAPI_CONFIG.BASE_URL}${TIANAPI_CONFIG.ENDPOINTS.zodiacMatch}`,
  140. method: 'GET',
  141. data: {
  142. key: TIANAPI_CONFIG.API_KEY,
  143. me: myZodiac,
  144. he: targetZodiac
  145. },
  146. timeout: 10000,
  147. success: (res) => {
  148. console.log('🌐 网络请求成功,原始响应:', res)
  149. resolve(res)
  150. },
  151. fail: (err) => {
  152. console.error('🌐 网络请求失败,错误信息:', err)
  153. reject(new Error(`网络请求失败: ${err.errMsg || err.message || '未知网络错误'}`))
  154. }
  155. })
  156. })
  157. console.log('📡 配对API完整响应:', {
  158. statusCode: response.statusCode,
  159. data: response.data,
  160. header: response.header,
  161. cookies: response.cookies
  162. })
  163. // 检查响应是否存在
  164. if (!response) {
  165. console.error('❌ 响应对象为空')
  166. throw new Error('网络响应为空,可能是域名配置或网络问题')
  167. }
  168. // 检查HTTP状态码
  169. if (response.statusCode !== 200) {
  170. console.error('❌ HTTP状态码错误:', response.statusCode)
  171. throw new Error(`HTTP错误: ${response.statusCode}`)
  172. }
  173. // 检查响应数据是否存在
  174. if (!response.data) {
  175. console.error('❌ API响应数据为空')
  176. throw new Error('API响应数据为空')
  177. }
  178. // 检查API业务状态码
  179. if (response.data.code !== 200) {
  180. console.error('❌ API业务错误:', {
  181. code: response.data.code,
  182. msg: response.data.msg || '未知错误'
  183. })
  184. throw new Error(response.data.msg || `API错误(code: ${response.data.code})`)
  185. }
  186. // 检查result数据
  187. const result = response.data.result
  188. if (!result) {
  189. console.error('❌ API返回结果为空')
  190. throw new Error('API返回结果为空')
  191. }
  192. console.log('✅ 配对查询成功,数据:', result)
  193. return {
  194. title: result.title || '配对分析',
  195. malePerspective: result.mcontent || '', // 男性视角
  196. femalePerspective: result.fcontent || '', // 女性视角
  197. malePerspective2: result.mcontent1 || '', // 男性视角2
  198. femalePerspective2: result.fcontent1 || '', // 女性视角2
  199. source: 'tianapi',
  200. updateTime: new Date().toLocaleString('zh-CN')
  201. }
  202. } catch (error) {
  203. console.error('❌ 生肖配对查询失败')
  204. console.error('错误类型:', error.name || 'Unknown')
  205. console.error('错误信息:', error.message || error.errMsg || '未知错误')
  206. console.error('完整错误:', error)
  207. // 友好的用户提示
  208. uni.showToast({
  209. title: '配对查询失败,使用本地数据',
  210. icon: 'none',
  211. duration: 2000
  212. })
  213. return null
  214. }
  215. }
  216. /**
  217. * 解析运势文本为分数
  218. * 根据关键词判断分数
  219. */
  220. function parseFortune(text) {
  221. if (!text) return 75
  222. // 正面关键词
  223. const positiveWords = ['佳', '好', '旺', '顺', '吉', '高', '升', '涨', '强']
  224. // 负面关键词
  225. const negativeWords = ['差', '弱', '低', '降', '凶', '衰', '险', '忌']
  226. let score = 75 // 基础分数
  227. // 检查正面词
  228. for (let word of positiveWords) {
  229. if (text.includes(word)) {
  230. score += 5
  231. }
  232. }
  233. // 检查负面词
  234. for (let word of negativeWords) {
  235. if (text.includes(word)) {
  236. score -= 5
  237. }
  238. }
  239. // 限制分数范围 60-95
  240. return Math.max(60, Math.min(95, score))
  241. }
  242. /**
  243. * 统一的获取运势接口
  244. * 优先使用API,失败则降级到本地
  245. */
  246. export async function getTodayFortune(zodiac) {
  247. return await getZodiacFortuneFromAPI(zodiac)
  248. }
  249. /**
  250. * 获取星座运势(如果需要)
  251. */
  252. export async function getConstellationFortune(constellation) {
  253. if (!validateConfig()) {
  254. return null
  255. }
  256. try {
  257. const response = await uni.request({
  258. url: `${TIANAPI_CONFIG.BASE_URL}${TIANAPI_CONFIG.ENDPOINTS.constellation}`,
  259. method: 'GET',
  260. data: {
  261. key: TIANAPI_CONFIG.API_KEY,
  262. astro: constellation
  263. },
  264. timeout: 5000
  265. })
  266. if (response.statusCode === 200 && response.data.code === 200) {
  267. return response.data.result
  268. }
  269. } catch (error) {
  270. console.error('获取星座运势失败:', error)
  271. }
  272. return null
  273. }
  274. /**
  275. * 测试API连接
  276. */
  277. export async function testAPIConnection() {
  278. if (!validateConfig()) {
  279. return {
  280. success: false,
  281. message: '请先配置API Key'
  282. }
  283. }
  284. try {
  285. console.log('🧪 开始测试API连接...')
  286. const result = await getZodiacFortuneFromAPI('鼠')
  287. // 检查是否真的是API数据
  288. if (result.source === 'tianapi') {
  289. return {
  290. success: true,
  291. message: 'API连接成功!',
  292. data: result
  293. }
  294. } else {
  295. return {
  296. success: false,
  297. message: 'API调用失败,已降级到本地数据',
  298. data: result
  299. }
  300. }
  301. } catch (error) {
  302. return {
  303. success: false,
  304. message: 'API连接失败:' + (error.message || error.errMsg || '未知错误'),
  305. error: error
  306. }
  307. }
  308. }
  309. /**
  310. * 🔧 网络连接诊断工具
  311. */
  312. export async function diagnoseNetwork() {
  313. console.log('🔧 开始网络诊断...')
  314. const diagnostics = {
  315. timestamp: new Date().toLocaleString('zh-CN'),
  316. environment: {
  317. platform: uni.getSystemInfoSync().platform,
  318. version: uni.getSystemInfoSync().version,
  319. SDKVersion: uni.getSystemInfoSync().SDKVersion
  320. },
  321. tests: {}
  322. }
  323. // 测试1: 基础网络连接
  324. try {
  325. console.log('📡 测试基础网络连接...')
  326. const testResponse = await new Promise((resolve, reject) => {
  327. uni.request({
  328. url: 'https://www.baidu.com',
  329. method: 'GET',
  330. timeout: 5000,
  331. success: resolve,
  332. fail: reject
  333. })
  334. })
  335. diagnostics.tests.basicNetwork = {
  336. success: true,
  337. statusCode: testResponse.statusCode,
  338. message: '网络连接正常'
  339. }
  340. console.log('✅ 基础网络连接正常')
  341. } catch (error) {
  342. diagnostics.tests.basicNetwork = {
  343. success: false,
  344. error: error.errMsg || error.message,
  345. message: '基础网络连接失败'
  346. }
  347. console.error('❌ 基础网络连接失败:', error)
  348. }
  349. // 测试2: HTTPS协议测试
  350. try {
  351. console.log('🔒 测试HTTPS协议支持...')
  352. const httpsResponse = await new Promise((resolve, reject) => {
  353. uni.request({
  354. url: 'https://httpbin.org/get',
  355. method: 'GET',
  356. timeout: 8000,
  357. success: resolve,
  358. fail: reject
  359. })
  360. })
  361. diagnostics.tests.httpsSupport = {
  362. success: true,
  363. statusCode: httpsResponse.statusCode,
  364. message: 'HTTPS协议支持正常'
  365. }
  366. console.log('✅ HTTPS协议支持正常')
  367. } catch (error) {
  368. diagnostics.tests.httpsSupport = {
  369. success: false,
  370. error: error.errMsg || error.message,
  371. message: 'HTTPS协议测试失败'
  372. }
  373. console.error('❌ HTTPS协议测试失败:', error)
  374. }
  375. // 测试3: 天行数据域名连通性
  376. try {
  377. console.log('🌐 测试天行数据域名连通性...')
  378. const tianApiResponse = await new Promise((resolve, reject) => {
  379. uni.request({
  380. url: 'https://apis.tianapi.com',
  381. method: 'GET',
  382. timeout: 8000,
  383. success: resolve,
  384. fail: reject
  385. })
  386. })
  387. diagnostics.tests.tianApiDomain = {
  388. success: true,
  389. statusCode: tianApiResponse.statusCode,
  390. message: '天行数据域名可访问'
  391. }
  392. console.log('✅ 天行数据域名可访问')
  393. } catch (error) {
  394. diagnostics.tests.tianApiDomain = {
  395. success: false,
  396. error: error.errMsg || error.message,
  397. message: '天行数据域名无法访问'
  398. }
  399. console.error('❌ 天行数据域名无法访问:', error)
  400. }
  401. return diagnostics
  402. }
  403. /**
  404. * 详细的API诊断工具
  405. */
  406. export async function diagnoseAPI() {
  407. console.log('🔧 开始API诊断...')
  408. const diagnostics = {
  409. config: {
  410. hasApiKey: !!TIANAPI_CONFIG.API_KEY,
  411. apiKey: TIANAPI_CONFIG.API_KEY ? TIANAPI_CONFIG.API_KEY.substring(0, 8) + '...' : '未配置',
  412. baseUrl: TIANAPI_CONFIG.BASE_URL,
  413. endpoint: TIANAPI_CONFIG.ENDPOINTS.zodiac
  414. },
  415. network: {},
  416. apiResponse: {}
  417. }
  418. // 测试基础网络连接
  419. try {
  420. console.log('📡 测试网络连接...')
  421. const testUrl = `${TIANAPI_CONFIG.BASE_URL}${TIANAPI_CONFIG.ENDPOINTS.zodiac}`
  422. diagnostics.network.testUrl = testUrl
  423. const response = await uni.request({
  424. url: testUrl,
  425. method: 'GET',
  426. data: {
  427. key: TIANAPI_CONFIG.API_KEY,
  428. name: '鼠'
  429. },
  430. timeout: 10000
  431. })
  432. diagnostics.network.success = true
  433. diagnostics.network.statusCode = response.statusCode
  434. diagnostics.apiResponse = response.data
  435. console.log('✅ 网络连接成功')
  436. console.log('响应:', response.data)
  437. } catch (error) {
  438. diagnostics.network.success = false
  439. diagnostics.network.error = error.errMsg || error.message
  440. console.error('❌ 网络连接失败:', error)
  441. }
  442. return diagnostics
  443. }
  444. export default {
  445. getTodayFortune,
  446. getZodiacFortuneFromAPI,
  447. getZodiacMatch,
  448. getConstellationFortune,
  449. testAPIConnection,
  450. diagnoseAPI,
  451. diagnoseNetwork
  452. }