wuxing-sandbox.js 4.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140
  1. /**
  2. * 五行能量沙盘 — 成员切换与数值解析工具。
  3. *
  4. * 沙盘里的数据有三类:
  5. * - personalData:当前登录用户(或个人视角)的沙盘数据
  6. * - members:家庭沙盘返回的所有成员数据
  7. * - familyScores:家庭聚合数据
  8. *
  9. * 组件只负责渲染,成员列表、当前选中项和最终展示分数都通过这里的纯函数解析,
  10. * 避免“切换了成员但数值仍是本人”的问题。
  11. */
  12. function scoreOf(data) {
  13. return {
  14. body: data && data.bodyScore != null ? data.bodyScore : 0,
  15. mind: data && data.mindScore != null ? data.mindScore : 0,
  16. wisdom: data && data.wisdomScore != null ? data.wisdomScore : 0,
  17. action: data && data.actionScore != null ? data.actionScore : 0,
  18. wealth: data && data.wealthScore != null ? data.wealthScore : 0
  19. }
  20. }
  21. function memberKey(member) {
  22. if (!member) return ''
  23. if (member.memberId != null) {
  24. return String(member.memberId) + '|' + String(member.memberType || '')
  25. }
  26. return 'name|' + String(member.name || '')
  27. }
  28. export function dedupeMembers(members) {
  29. const list = Array.isArray(members) ? members : []
  30. const seen = {}
  31. const result = []
  32. for (let i = 0; i < list.length; i++) {
  33. const member = list[i]
  34. if (!member) continue
  35. const key = memberKey(member)
  36. if (seen[key]) continue
  37. seen[key] = true
  38. result.push(member)
  39. }
  40. return result
  41. }
  42. export function getSelfMember(personalData) {
  43. if (!personalData || !Array.isArray(personalData.members) || !personalData.members.length) {
  44. return null
  45. }
  46. return personalData.members[0]
  47. }
  48. export function findMemberById(members, memberId) {
  49. if (memberId == null) return null
  50. const list = dedupeMembers(members)
  51. for (let i = 0; i < list.length; i++) {
  52. if (String(list[i].memberId) === String(memberId)) return list[i]
  53. }
  54. return null
  55. }
  56. export function buildMemberOptions(members, personalData) {
  57. const self = getSelfMember(personalData)
  58. const selfId = self && self.memberId != null ? String(self.memberId) : null
  59. const options = [{
  60. key: 'personal',
  61. label: '本人',
  62. viewMode: 'personal',
  63. memberId: self && self.memberId != null ? self.memberId : null,
  64. member: null
  65. }]
  66. const list = dedupeMembers(members)
  67. for (let i = 0; i < list.length; i++) {
  68. const member = list[i]
  69. if (selfId != null && String(member.memberId) === selfId) continue
  70. options.push({
  71. key: 'member-' + memberKey(member),
  72. label: member.name || '家庭成员',
  73. viewMode: 'member',
  74. memberId: member.memberId,
  75. member
  76. })
  77. }
  78. options.push({
  79. key: 'family',
  80. label: '全家',
  81. viewMode: 'family',
  82. memberId: null,
  83. member: null
  84. })
  85. return options
  86. }
  87. export function resolveSandboxScores(viewMode, familyScores, personalData, currentMember) {
  88. let source = personalData
  89. if (viewMode === 'family') {
  90. source = familyScores
  91. } else if (viewMode === 'member' && currentMember) {
  92. source = currentMember
  93. }
  94. const s = scoreOf(source)
  95. return [s.body, s.mind, s.wisdom, s.action, s.wealth]
  96. }
  97. export function resolveSandboxOverall(viewMode, familyScores, personalData, currentMember) {
  98. let source = personalData
  99. if (viewMode === 'family') {
  100. source = familyScores
  101. } else if (viewMode === 'member' && currentMember) {
  102. source = currentMember
  103. }
  104. return source && source.overallScore != null ? source.overallScore : 0
  105. }
  106. /**
  107. * 太极图中心点击:本人 -> 其他成员 -> 全家 -> 本人。
  108. * 找不到当前项时从第一项重新开始,保证不会卡死。
  109. */
  110. export function nextSandboxSelection(options, viewMode, memberId) {
  111. const list = Array.isArray(options) && options.length ? options : [
  112. { key: 'personal', label: '本人', viewMode: 'personal', memberId: null },
  113. { key: 'family', label: '全家', viewMode: 'family', memberId: null }
  114. ]
  115. let current = -1
  116. for (let i = 0; i < list.length; i++) {
  117. const option = list[i]
  118. if (option.viewMode !== viewMode) continue
  119. if (viewMode === 'member' && String(option.memberId) !== String(memberId)) continue
  120. current = i
  121. break
  122. }
  123. const next = list[(current + 1) % list.length]
  124. return {
  125. viewMode: next.viewMode,
  126. memberId: next.memberId != null ? next.memberId : null,
  127. label: next.label
  128. }
  129. }