|
|
@@ -262,6 +262,7 @@ import RadarChart from '../../components/RadarChart.vue'
|
|
|
import ArticleFeed from '../../components/ArticleFeed.vue'
|
|
|
import ReportUploadCard from '../../components/report-upload-card.vue'
|
|
|
import { parseDate } from '../../utils/format.js'
|
|
|
+import { ensureDimensionRegistry, getRadarConfig, isRegistryReady, WEALTH_CHILD_LABEL } from '../../composables/useDimensionRegistry.js'
|
|
|
import fontScaleMixin from '@/mixins/font-scale.js'
|
|
|
import shareMixin from '../../components/share-mixin.js'
|
|
|
|
|
|
@@ -324,7 +325,10 @@ export default {
|
|
|
childrenList: [],
|
|
|
relationshipEmpty: false,
|
|
|
// 登录浮层打开标志(打开期间隐藏演示雷达,避免原生 canvas 盖在浮层之上)
|
|
|
- loginSheetVisible: false
|
|
|
+ loginSheetVisible: false,
|
|
|
+ // 统一维度注册中心是否就绪(成功取到 tree 后由 ensureDimensionRegistry 置位)
|
|
|
+ // 未就绪时主页雷达回落硬编码兜底,保证后端未上线 / 接口异常时页面不崩
|
|
|
+ registryReady: false
|
|
|
}
|
|
|
},
|
|
|
computed: {
|
|
|
@@ -337,23 +341,23 @@ export default {
|
|
|
return tab ? tab.color : BrandColors.body
|
|
|
},
|
|
|
currentDimensions: function() {
|
|
|
- if (this.currentTab === 'cognitive') {
|
|
|
- return [{ label:'记忆力',key:'memory'},{ label:'注意力',key:'attention'},{ label:'逻辑推理',key:'logic'},{ label:'空间想象',key:'spatial'},{ label:'感知能力',key:'perception'},{ label:'专注力',key:'focus'},{ label:'加工速度',key:'processingSpeed' }]
|
|
|
- }
|
|
|
- if (this.currentTab === 'mental') {
|
|
|
- return [{ label:'开放性',key:'openness'},{ label:'尽责性',key:'conscientiousness'},{ label:'外向性',key:'extraversion'},{ label:'宜人性',key:'agreeableness'},{ label:'神经质',key:'neuroticism'},{ label:'自主性',key:'driveAutonomy'},{ label:'胜任感',key:'driveCompetence'},{ label:'归属感',key:'driveRelatedness'},{ label:'情绪稳定性',key:'emotionStability'},{ label:'自我概念',key:'selfConceptOverall' }]
|
|
|
- }
|
|
|
- if (this.currentTab === 'relationship') {
|
|
|
- return [{ label:'亲子信任',key:'parentTrust'},{ label:'亲子亲密度',key:'parentIntimacy'},{ label:'沟通质量',key:'communication'},{ label:'关系健康度',key:'healthStatus'},{ label:'最近互动',key:'lastInteraction' }]
|
|
|
- }
|
|
|
- if (this.currentTab === 'wealth') {
|
|
|
+ // 配置驱动:从统一维度注册中心 tree 取该 tab 根节点的 children 作为维度清单
|
|
|
+ var config = getRadarConfig(this.currentTab)
|
|
|
+ if (this.registryReady && config && config.length > 0) {
|
|
|
var isChild = !!uni.getStorageSync('currentChildId')
|
|
|
- if (isChild) {
|
|
|
- return [{ label:'学业能力',key:'skill'},{ label:'利他贡献',key:'altruism'},{ label:'积分积累',key:'income'},{ label:'财务素养',key:'fx' }]
|
|
|
- }
|
|
|
- return [{ label:'个人能力',key:'skill'},{ label:'利他贡献',key:'altruism'},{ label:'CF值积累',key:'income'},{ label:'财务素养',key:'fx' }]
|
|
|
+ var self = this
|
|
|
+ return config.map(function(c) {
|
|
|
+ var label = c.label
|
|
|
+ // 财富子维度在「成员(儿童)」语境下使用更贴近儿童的文案(与改造前字面量一致)
|
|
|
+ if (self.currentTab === 'wealth' && isChild && WEALTH_CHILD_LABEL[c.code]) {
|
|
|
+ label = WEALTH_CHILD_LABEL[c.code]
|
|
|
+ }
|
|
|
+ // label 供 RadarChart 画维度名;key 供(若有)点击透传;code 保留注册中心维度码
|
|
|
+ return { label: label, key: c.code, code: c.code }
|
|
|
+ })
|
|
|
}
|
|
|
- return [{ label:'生长发育',key:'growth'},{ label:'睡眠质量',key:'sleep'},{ label:'视力健康',key:'vision'},{ label:'免疫力',key:'immunity'},{ label:'营养均衡',key:'nutrition'},{ label:'肠胃健康',key:'gut'},{ label:'运动活力',key:'exercise' }]
|
|
|
+ // 过渡兜底:注册中心未就绪或某根无子维 → 回落现有硬编码清单(后端未上线 / 接口异常时页面不崩)
|
|
|
+ return this._fallbackDimensions(this.currentTab)
|
|
|
},
|
|
|
currentScores: function() {
|
|
|
if (this.chartIsEmpty) {
|
|
|
@@ -361,55 +365,16 @@ export default {
|
|
|
for (var i = 0; i < dims.length; i++) scores.push(0)
|
|
|
return scores
|
|
|
}
|
|
|
- if (this.currentTab === 'cognitive') {
|
|
|
- return [
|
|
|
- this._cognitiveScore('memoryScore'),
|
|
|
- this._cognitiveScore('attentionScore'),
|
|
|
- this._cognitiveScore('logicScore'),
|
|
|
- this._cognitiveScore('spatialScore'),
|
|
|
- this._cognitiveScore('perceptionScore'),
|
|
|
- this._cognitiveScore('focusScore'),
|
|
|
- this._cognitiveScore('processingSpeedScore')
|
|
|
- ]
|
|
|
- }
|
|
|
- if (this.currentTab === 'mental') {
|
|
|
- return [
|
|
|
- this._emiScore('opennessScore'),
|
|
|
- this._emiScore('conscientiousnessScore'),
|
|
|
- this._emiScore('extraversionScore'),
|
|
|
- this._emiScore('agreeablenessScore'),
|
|
|
- this._emiScore('neuroticismScore'),
|
|
|
- this._emiScore('driveAutonomy'),
|
|
|
- this._emiScore('driveCompetence'),
|
|
|
- this._emiScore('driveRelatedness'),
|
|
|
- this._emiScore('emotionStability'),
|
|
|
- this._emiScore('selfConceptOverall')
|
|
|
- ]
|
|
|
- }
|
|
|
- if (this.currentTab === 'relationship') {
|
|
|
- return [
|
|
|
- this._relScore('trustScore'),
|
|
|
- this._relScore('intimacyScore'),
|
|
|
- this._relScore('communicationScore'),
|
|
|
- this._relScore('totalScore'),
|
|
|
- 0
|
|
|
- ]
|
|
|
- }
|
|
|
- if (this.currentTab === 'wealth') {
|
|
|
- var d = this.wealthDetail
|
|
|
- if (!d) return [0, 0, 0, 0]
|
|
|
- return [d.wealthSkill || 0, d.wealthAltruism || 0, d.wealthIncome || 0, d.wealthFx || 0]
|
|
|
- }
|
|
|
- // body: 从 API 真实维度数据取分
|
|
|
- if (this.bodyData && this.bodyData.dimensions && this.bodyData.dimensions.length > 0) {
|
|
|
- return this.bodyData.dimensions.map(function(d) { return Number(d.score) || 0 })
|
|
|
- }
|
|
|
- // body: fallback to demo
|
|
|
- if (this.reports.length > 0) {
|
|
|
- var latest = this.reports[0]
|
|
|
- if (latest.overallScore) return [72, 68, 75, 80, 70, 78, 82]
|
|
|
+ // 配置驱动:与 currentDimensions 同源同序遍历注册中心配置,按 scoreField 取分
|
|
|
+ var config = getRadarConfig(this.currentTab)
|
|
|
+ if (this.registryReady && config && config.length > 0) {
|
|
|
+ var self = this
|
|
|
+ return config.map(function(c) {
|
|
|
+ return self._readRegistryScore(self.currentTab, c.code, c.scoreField)
|
|
|
+ })
|
|
|
}
|
|
|
- return [72, 68, 75, 80, 70, 78, 82]
|
|
|
+ // 过渡兜底:注册中心未就绪 → 回落现有硬编码取分逻辑(与改造前一致)
|
|
|
+ return this._fallbackScores(this.currentTab)
|
|
|
},
|
|
|
currentAvgScores: function() {
|
|
|
if (this.chartIsEmpty) return []
|
|
|
@@ -470,6 +435,13 @@ export default {
|
|
|
this.loadHealthData()
|
|
|
this.loadPlanList()
|
|
|
this.loadPendingSurveys()
|
|
|
+ // 触发统一维度注册中心树拉取(主页雷达配置驱动取数;失败则回落硬编码兜底)
|
|
|
+ var self = this
|
|
|
+ ensureDimensionRegistry().then(function() {
|
|
|
+ self.registryReady = isRegistryReady()
|
|
|
+ }).catch(function() {
|
|
|
+ self.registryReady = false
|
|
|
+ })
|
|
|
} else {
|
|
|
this.pendingSurveys = []
|
|
|
}
|
|
|
@@ -499,6 +471,144 @@ export default {
|
|
|
var v = this.energySandbox[key]
|
|
|
return (typeof v === 'number' && v > 0) ? v : 0
|
|
|
},
|
|
|
+ /**
|
|
|
+ * 过渡兜底:返回某 tab 的硬编码维度清单(与改造前字面量一致)。
|
|
|
+ * 仅当注册中心未就绪时使用,保证后端未上线 / 接口异常时页面不崩。
|
|
|
+ * @param {string} tab
|
|
|
+ * @returns {Array<{label:string,key:string}>}
|
|
|
+ */
|
|
|
+ _fallbackDimensions: function(tab) {
|
|
|
+ if (tab === 'cognitive') {
|
|
|
+ return [{ label:'记忆力',key:'memory'},{ label:'注意力',key:'attention'},{ label:'逻辑推理',key:'logic'},{ label:'空间想象',key:'spatial'},{ label:'感知能力',key:'perception'},{ label:'专注力',key:'focus'},{ label:'加工速度',key:'processingSpeed' }]
|
|
|
+ }
|
|
|
+ if (tab === 'mental') {
|
|
|
+ return [{ label:'开放性',key:'openness'},{ label:'尽责性',key:'conscientiousness'},{ label:'外向性',key:'extraversion'},{ label:'宜人性',key:'agreeableness'},{ label:'神经质',key:'neuroticism'},{ label:'自主性',key:'driveAutonomy'},{ label:'胜任感',key:'driveCompetence'},{ label:'归属感',key:'driveRelatedness'},{ label:'情绪稳定性',key:'emotionStability'},{ label:'自我概念',key:'selfConceptOverall' }]
|
|
|
+ }
|
|
|
+ if (tab === 'relationship') {
|
|
|
+ return [{ label:'亲子信任',key:'parentTrust'},{ label:'亲子亲密度',key:'parentIntimacy'},{ label:'沟通质量',key:'communication'},{ label:'关系健康度',key:'healthStatus'},{ label:'最近互动',key:'lastInteraction' }]
|
|
|
+ }
|
|
|
+ if (tab === 'wealth') {
|
|
|
+ var isChild = !!uni.getStorageSync('currentChildId')
|
|
|
+ if (isChild) {
|
|
|
+ return [{ label:'学业能力',key:'skill'},{ label:'利他贡献',key:'altruism'},{ label:'积分积累',key:'income'},{ label:'财务素养',key:'fx' }]
|
|
|
+ }
|
|
|
+ return [{ label:'个人能力',key:'skill'},{ label:'利他贡献',key:'altruism'},{ label:'CF值积累',key:'income'},{ label:'财务素养',key:'fx' }]
|
|
|
+ }
|
|
|
+ return [{ label:'生长发育',key:'growth'},{ label:'睡眠质量',key:'sleep'},{ label:'视力健康',key:'vision'},{ label:'免疫力',key:'immunity'},{ label:'营养均衡',key:'nutrition'},{ label:'肠胃健康',key:'gut'},{ label:'运动活力',key:'exercise' }]
|
|
|
+ },
|
|
|
+ /**
|
|
|
+ * 过渡兜底:返回某 tab 的硬编码取分(与改造前字面量一致)。
|
|
|
+ * @param {string} tab
|
|
|
+ * @returns {Array<number>}
|
|
|
+ */
|
|
|
+ _fallbackScores: function(tab) {
|
|
|
+ if (tab === 'cognitive') {
|
|
|
+ return [
|
|
|
+ this._cognitiveScore('memoryScore'),
|
|
|
+ this._cognitiveScore('attentionScore'),
|
|
|
+ this._cognitiveScore('logicScore'),
|
|
|
+ this._cognitiveScore('spatialScore'),
|
|
|
+ this._cognitiveScore('perceptionScore'),
|
|
|
+ this._cognitiveScore('focusScore'),
|
|
|
+ this._cognitiveScore('processingSpeedScore')
|
|
|
+ ]
|
|
|
+ }
|
|
|
+ if (tab === 'mental') {
|
|
|
+ return [
|
|
|
+ this._emiScore('opennessScore'),
|
|
|
+ this._emiScore('conscientiousnessScore'),
|
|
|
+ this._emiScore('extraversionScore'),
|
|
|
+ this._emiScore('agreeablenessScore'),
|
|
|
+ this._emiScore('neuroticismScore'),
|
|
|
+ this._emiScore('driveAutonomy'),
|
|
|
+ this._emiScore('driveCompetence'),
|
|
|
+ this._emiScore('driveRelatedness'),
|
|
|
+ this._emiScore('emotionStability'),
|
|
|
+ this._emiScore('selfConceptOverall')
|
|
|
+ ]
|
|
|
+ }
|
|
|
+ if (tab === 'relationship') {
|
|
|
+ return [
|
|
|
+ this._relScore('trustScore'),
|
|
|
+ this._relScore('intimacyScore'),
|
|
|
+ this._relScore('communicationScore'),
|
|
|
+ this._relScore('totalScore'),
|
|
|
+ 0
|
|
|
+ ]
|
|
|
+ }
|
|
|
+ if (tab === 'wealth') {
|
|
|
+ var d = this.wealthDetail
|
|
|
+ if (!d) return [0, 0, 0, 0]
|
|
|
+ return [d.wealthSkill || 0, d.wealthAltruism || 0, d.wealthIncome || 0, d.wealthFx || 0]
|
|
|
+ }
|
|
|
+ // body: 从 API 真实维度数据取分
|
|
|
+ if (this.bodyData && this.bodyData.dimensions && this.bodyData.dimensions.length > 0) {
|
|
|
+ return this.bodyData.dimensions.map(function(dItem) { return Number(dItem.score) || 0 })
|
|
|
+ }
|
|
|
+ // body: fallback to demo
|
|
|
+ if (this.reports.length > 0) {
|
|
|
+ var latest = this.reports[0]
|
|
|
+ if (latest.overallScore) return [72, 68, 75, 80, 70, 78, 82]
|
|
|
+ }
|
|
|
+ return [72, 68, 75, 80, 70, 78, 82]
|
|
|
+ },
|
|
|
+ /**
|
|
|
+ * 配置驱动取分:按 tab 与注册中心节点的 scoreField / code 从对应分数包取分。
|
|
|
+ * 包缺失或值非数字 → 0(保持现有零填充行为)。与改造前取分口径逐一对齐。
|
|
|
+ * @param {string} tab
|
|
|
+ * @param {string} code 注册中心节点 code(body 类为 body.growth)
|
|
|
+ * @param {string} scoreField legacyAlias 首元素(取分字段名)
|
|
|
+ * @returns {number}
|
|
|
+ */
|
|
|
+ _readRegistryScore: function(tab, code, scoreField) {
|
|
|
+ if (tab === 'body') {
|
|
|
+ // body 维度按 dimension 字段匹配:兼容两种格式——
|
|
|
+ // ① 当前后端 /api/dimension/overview 仍返回 legacy 码(growth/sleep/...,见 DimensionScoreServiceImpl.DIMENSIONS),
|
|
|
+ // 此时与 legacyAlias 首元素(scoreField)匹配;
|
|
|
+ // ② 后续后端迁移为统一码(body.growth/...)后,与注册中心节点 code 匹配。
|
|
|
+ var dims = this.bodyData && this.bodyData.dimensions
|
|
|
+ if (!dims || !dims.length) return 0
|
|
|
+ for (var i = 0; i < dims.length; i++) {
|
|
|
+ var dItem = dims[i]
|
|
|
+ if (dItem && (dItem.dimension === code || dItem.dimension === scoreField)) {
|
|
|
+ var v = Number(dItem.score)
|
|
|
+ return (typeof v === 'number' && !isNaN(v)) ? v : 0
|
|
|
+ }
|
|
|
+ }
|
|
|
+ return 0
|
|
|
+ }
|
|
|
+ if (tab === 'cognitive') {
|
|
|
+ if (!this.cognitiveData) return 0
|
|
|
+ var cv = this.cognitiveData[scoreField]
|
|
|
+ return (typeof cv === 'number' && cv > 0) ? cv : 0
|
|
|
+ }
|
|
|
+ if (tab === 'mental') {
|
|
|
+ if (!this.emiData) return 0
|
|
|
+ var mv = this.emiData[scoreField]
|
|
|
+ return (typeof mv === 'number' && mv > 0) ? mv : 0
|
|
|
+ }
|
|
|
+ if (tab === 'relationship') {
|
|
|
+ // 最近互动是日期字段,恒为 0(与改造前字面量 0 一致)
|
|
|
+ if (scoreField === 'lastInteractionAt') return 0
|
|
|
+ if (!this.relationshipData || this.relationshipData.length === 0) return 0
|
|
|
+ var total = 0, count = 0
|
|
|
+ for (var r = 0; r < this.relationshipData.length; r++) {
|
|
|
+ var item = this.relationshipData[r]
|
|
|
+ if (item && item[scoreField] != null) {
|
|
|
+ total += Number(item[scoreField])
|
|
|
+ count++
|
|
|
+ }
|
|
|
+ }
|
|
|
+ return count > 0 ? Math.round(total / count) : 0
|
|
|
+ }
|
|
|
+ if (tab === 'wealth') {
|
|
|
+ var wd = this.wealthDetail
|
|
|
+ if (!wd) return 0
|
|
|
+ var wv = wd[scoreField]
|
|
|
+ return (typeof wv === 'number' && wv > 0) ? wv : 0
|
|
|
+ }
|
|
|
+ return 0
|
|
|
+ },
|
|
|
switchTab: function(code) { this.currentTab = code },
|
|
|
goPage: function(url) { uni.navigateTo({ url: url }) },
|
|
|
// 登录浮层打开/关闭(隐藏演示雷达,规避原生 canvas 层级高于浮层的问题)
|