|
|
@@ -74,14 +74,26 @@
|
|
|
<view class="section-title">📝 确认问卷内容</view>
|
|
|
<view class="hint-text">请核对以下问卷信息准确无误后,手写签名确认</view>
|
|
|
|
|
|
- <!-- 问卷内容摘要(按成员) -->
|
|
|
+ <!-- 问卷内容摘要(按成员,默认只展示关键项,可展开全部) -->
|
|
|
<view class="confirm-survey-list">
|
|
|
<view v-for="m in selectedMembers" :key="m.memberId" class="confirm-survey-member">
|
|
|
- <view class="confirm-member-name">{{ m.name }}</view>
|
|
|
+ <view class="confirm-member-head">
|
|
|
+ <text class="confirm-member-name">{{ m.name }}</text>
|
|
|
+ <text v-if="getMemberSignedAt(m.memberId)" class="confirm-member-signed">已签署 {{ getMemberSignedAt(m.memberId) }}</text>
|
|
|
+ </view>
|
|
|
<view class="confirm-summary-row" v-for="(line, li) in buildSurveySummary(m.memberId)" :key="li">
|
|
|
<text class="confirm-label">{{ line.label }}</text>
|
|
|
<text class="confirm-value">{{ line.value }}</text>
|
|
|
</view>
|
|
|
+ <view v-if="showFullSummary" class="confirm-extra-block">
|
|
|
+ <view class="confirm-summary-row" v-for="(line, li) in buildSurveyExtraSummary(m.memberId)" :key="li">
|
|
|
+ <text class="confirm-label">{{ line.label }}</text>
|
|
|
+ <text class="confirm-value">{{ line.value }}</text>
|
|
|
+ </view>
|
|
|
+ </view>
|
|
|
+ <view v-if="extraCount(m.memberId) > 0" class="confirm-toggle" @click="toggleFullSummary">
|
|
|
+ <text class="confirm-toggle-text">{{ showFullSummary ? '收起' : '展开其余 ' + extraCount(m.memberId) + ' 项' }}</text>
|
|
|
+ </view>
|
|
|
<view v-if="!hasMemberData(m.memberId)" class="confirm-empty">该成员未填写问卷内容</view>
|
|
|
</view>
|
|
|
</view>
|
|
|
@@ -92,8 +104,11 @@
|
|
|
<hand-signature
|
|
|
ref="signaturePad"
|
|
|
:value="signatureDataUrl"
|
|
|
+ :require-agree="true"
|
|
|
+ agree-text="我已阅读并确认上述问卷信息真实、准确,且由本人填写"
|
|
|
@confirm="onSignatureConfirm"
|
|
|
@clear="onSignatureClear"
|
|
|
+ @agree-change="onSignatureAgreeChange"
|
|
|
/>
|
|
|
|
|
|
<view class="btn-pair">
|
|
|
@@ -264,7 +279,9 @@ export default {
|
|
|
loading: false,
|
|
|
taskSubmitted: false,
|
|
|
// Step 3 签名确认
|
|
|
- signatureDataUrl: ''
|
|
|
+ signatureDataUrl: '',
|
|
|
+ // 确认页:是否展开非关键项
|
|
|
+ showFullSummary: false
|
|
|
}
|
|
|
},
|
|
|
computed: {
|
|
|
@@ -481,7 +498,8 @@ selectedMembers: function() {
|
|
|
selectedDiseases: self.parseDiseases(d.diseaseHistory),
|
|
|
medRows: self.parseMeds(d.medications),
|
|
|
noMedication: false,
|
|
|
- lifestyle: d.lifestyle ? self.parseLifestyle(d.lifestyle) : {}
|
|
|
+ lifestyle: d.lifestyle ? self.parseLifestyle(d.lifestyle) : {},
|
|
|
+ signedAt: d.signedAt || ''
|
|
|
})
|
|
|
}
|
|
|
}).catch(function() {})
|
|
|
@@ -760,67 +778,100 @@ selectedMembers: function() {
|
|
|
},
|
|
|
|
|
|
// ===== Step 3 签名确认 =====
|
|
|
- // 按成员生成问卷内容摘要(键值对列表)
|
|
|
- buildSurveySummary: function(memberId) {
|
|
|
+ // 构建某成员的全部问卷条目(primary=true 为确认页默认展示的关键项)
|
|
|
+ buildSurveyLines: function(memberId) {
|
|
|
var s = this.memberFormMap[String(memberId)] || null
|
|
|
var d = this.memberDietMap[String(memberId)] || null
|
|
|
var lines = []
|
|
|
- var push = function(label, value) {
|
|
|
+ var push = function(primary, label, value) {
|
|
|
if (value && String(value).trim() !== '' && value !== false && !(Array.isArray(value) && value.length === 0)) {
|
|
|
- lines.push({ label: label, value: Array.isArray(value) ? value.join('、') : String(value) })
|
|
|
+ lines.push({ primary: !!primary, label: label, value: Array.isArray(value) ? value.join('、') : String(value) })
|
|
|
}
|
|
|
}
|
|
|
+ // 多值合并为一行(忽略空值)
|
|
|
+ var join = function() {
|
|
|
+ var parts = []
|
|
|
+ for (var i = 0; i < arguments.length; i++) {
|
|
|
+ if (arguments[i]) parts.push(arguments[i])
|
|
|
+ }
|
|
|
+ return parts.join(' · ')
|
|
|
+ }
|
|
|
if (s) {
|
|
|
var f = s.form || {}
|
|
|
- push('身高', f.heightCm ? f.heightCm + ' cm' : '')
|
|
|
- push('体重', f.weightKg ? f.weightKg + ' kg' : '')
|
|
|
- push('血压', f.bloodPressure)
|
|
|
- push('空腹血糖', f.bloodGlucose ? f.bloodGlucose + ' mmol/L' : '')
|
|
|
- push('总胆固醇', s.lipidCholesterol ? s.lipidCholesterol + ' mmol/L' : '')
|
|
|
+ var ls = s.lifestyle || {}
|
|
|
+ // —— 关键项(默认展示)——
|
|
|
+ push(true, '身高/体重', join(f.heightCm ? f.heightCm + ' cm' : '', f.weightKg ? f.weightKg + ' kg' : '', ' / '))
|
|
|
+ push(true, '血压', f.bloodPressure)
|
|
|
+ push(true, '血糖/胆固醇', join(f.bloodGlucose ? '血糖 ' + f.bloodGlucose + ' mmol/L' : '',
|
|
|
+ s.lipidCholesterol ? '总胆固醇 ' + s.lipidCholesterol + ' mmol/L' : ''))
|
|
|
if (s.selectedDiseases && s.selectedDiseases.length > 0) {
|
|
|
- push('疾病史', s.selectedDiseases.map(function(x) { return x.name }).join('、'))
|
|
|
+ push(true, '疾病史', s.selectedDiseases.map(function(x) { return x.name }).join('、'))
|
|
|
}
|
|
|
- if (s.noMedication) push('用药', '无')
|
|
|
+ if (s.noMedication) push(true, '在服药物', '无')
|
|
|
else if (s.medRows && s.medRows.length > 0) {
|
|
|
- push('在服药物', s.medRows.map(function(x) { return x.name || '' }).filter(function(n) { return n }).join('、'))
|
|
|
+ push(true, '在服药物', s.medRows.map(function(x) { return x.name || '' }).filter(function(n) { return n }).join('、'))
|
|
|
}
|
|
|
- var ls = s.lifestyle || {}
|
|
|
- push('心情', ls.mood)
|
|
|
- push('睡眠时长', ls.sleepDuration)
|
|
|
- push('入睡时间', ls.bedtime)
|
|
|
- push('排便频率', ls.bowelFrequency)
|
|
|
- push('排便性状', ls.bowelForm)
|
|
|
- push('抗生素用药史', ls.antibioticHistory)
|
|
|
- if (ls.allergySymptoms && ls.allergySymptoms.length > 0) push('过敏表现', ls.allergySymptoms.join('、'))
|
|
|
- push('月经周期', ls.menstrualCycle)
|
|
|
- push('特殊时期', ls.specialPeriod)
|
|
|
- push('生长发育', ls.growthDevelopment)
|
|
|
- push('挑食情况', ls.pickyEating)
|
|
|
- push('骨质疏松风险', ls.osteoporosisRisk)
|
|
|
- push('跌倒风险', ls.fallRisk)
|
|
|
- push('屏幕时间', ls.screenTime)
|
|
|
- push('情绪状态', ls.teenMood)
|
|
|
- push('当前状态', ls.currentStatus)
|
|
|
- push('运动频率', ls.exerciseFrequency)
|
|
|
- push('运动时长', ls.exerciseDuration)
|
|
|
- if (f.notes) push('补充说明', f.notes)
|
|
|
+ push(true, '睡眠', join(ls.bedtime ? ls.bedtime + ' 入睡' : '', ls.sleepDuration))
|
|
|
+ push(true, '排便', join(ls.bowelFrequency, ls.bowelForm))
|
|
|
+ push(true, '心情', ls.mood)
|
|
|
+ push(true, '近2年抗生素', ls.antibioticHistory)
|
|
|
+ if (ls.allergySymptoms && ls.allergySymptoms.length > 0) push(true, '过敏表现', ls.allergySymptoms.join('、'))
|
|
|
+ if (d) {
|
|
|
+ push(true, '饮食结构', join(d.vegetableFruit, d.dairy, d.sugaryDrinks))
|
|
|
+ push(true, '饮食忌口', join(d.allergies, d.absoluteAvoid))
|
|
|
+ }
|
|
|
+ // —— 其余项(展开后展示)——
|
|
|
+ push(false, '月经周期', ls.menstrualCycle)
|
|
|
+ push(false, '特殊时期', ls.specialPeriod)
|
|
|
+ push(false, '生长发育', ls.growthDevelopment)
|
|
|
+ push(false, '挑食情况', ls.pickyEating)
|
|
|
+ push(false, '骨质疏松风险', ls.osteoporosisRisk)
|
|
|
+ push(false, '跌倒风险', ls.fallRisk)
|
|
|
+ push(false, '屏幕时间', ls.screenTime)
|
|
|
+ push(false, '情绪状态', ls.teenMood)
|
|
|
+ push(false, '当前状态', ls.currentStatus)
|
|
|
+ push(false, '运动频率', ls.exerciseFrequency)
|
|
|
+ push(false, '运动时长', ls.exerciseDuration)
|
|
|
+ push(false, '补充说明', f.notes)
|
|
|
+ } else if (d) {
|
|
|
+ push(true, '饮食结构', join(d.vegetableFruit, d.dairy, d.sugaryDrinks))
|
|
|
+ push(true, '饮食忌口', join(d.allergies, d.absoluteAvoid))
|
|
|
}
|
|
|
if (d) {
|
|
|
- push('食物过敏', d.allergies)
|
|
|
- push('绝对忌口', d.absoluteAvoid)
|
|
|
- push('必吃食物', d.mustEat)
|
|
|
- push('宗教饮食', d.religiousDiet && d.religiousDiet !== 'none' ? d.religiousDiet : '')
|
|
|
- if (Number(d.spiceLevel) > 0) push('辣度', d.spiceLevel)
|
|
|
- push('口味偏好', d.flavorPref)
|
|
|
- push('菜系偏好', d.cuisinePref)
|
|
|
- push('烹饪方式', d.cookingMethods)
|
|
|
- if (d.noPreference) push('饮食偏好', '无特殊偏好')
|
|
|
- push('蔬果量', d.vegetableFruit)
|
|
|
- push('乳制品', d.dairy)
|
|
|
- push('含糖饮料', d.sugaryDrinks)
|
|
|
+ push(false, '必吃食物', d.mustEat)
|
|
|
+ push(false, '宗教饮食', d.religiousDiet && d.religiousDiet !== 'none' ? d.religiousDiet : '')
|
|
|
+ if (Number(d.spiceLevel) > 0) push(false, '辣度', d.spiceLevel)
|
|
|
+ push(false, '口味偏好', d.flavorPref)
|
|
|
+ push(false, '菜系偏好', d.cuisinePref)
|
|
|
+ push(false, '烹饪方式', d.cookingMethods)
|
|
|
+ if (d.noPreference) push(false, '饮食偏好', '无特殊偏好')
|
|
|
}
|
|
|
return lines
|
|
|
},
|
|
|
+ // 关键项(确认页默认展示)
|
|
|
+ buildSurveySummary: function(memberId) {
|
|
|
+ return this.buildSurveyLines(memberId).filter(function(l) { return l.primary })
|
|
|
+ },
|
|
|
+ // 其余项(点击展开后展示)
|
|
|
+ buildSurveyExtraSummary: function(memberId) {
|
|
|
+ return this.buildSurveyLines(memberId).filter(function(l) { return !l.primary })
|
|
|
+ },
|
|
|
+ extraCount: function(memberId) {
|
|
|
+ return this.buildSurveyExtraSummary(memberId).length
|
|
|
+ },
|
|
|
+ toggleFullSummary: function() {
|
|
|
+ this.showFullSummary = !this.showFullSummary
|
|
|
+ },
|
|
|
+ // 该成员已签署时间(问卷内容变更后后端会置空)
|
|
|
+ getMemberSignedAt: function(memberId) {
|
|
|
+ var s = this.memberFormMap[String(memberId)]
|
|
|
+ var v = s && s.signedAt
|
|
|
+ return v ? this.formatTime(v) : ''
|
|
|
+ },
|
|
|
+ // 取消勾选同意 → 作废已确认签名
|
|
|
+ onSignatureAgreeChange: function(agreed) {
|
|
|
+ if (!agreed) this.signatureDataUrl = ''
|
|
|
+ },
|
|
|
// 该成员是否有问卷/饮食数据可供确认
|
|
|
hasMemberData: function(memberId) {
|
|
|
var s = this.memberFormMap[String(memberId)]
|
|
|
@@ -859,6 +910,8 @@ selectedMembers: function() {
|
|
|
}
|
|
|
Promise.all(sigTasks).then(function() {
|
|
|
self.loading = false
|
|
|
+ // 本地回显签署时间(服务端以 health_status.signed_at 为准)
|
|
|
+ self.stampLocalSignedAt()
|
|
|
self.step = 4
|
|
|
self.generatePlan()
|
|
|
}).catch(function() {
|
|
|
@@ -868,6 +921,18 @@ selectedMembers: function() {
|
|
|
self.generatePlan()
|
|
|
})
|
|
|
},
|
|
|
+ // 签名成功后本地回显签署时间(格式 yyyy-MM-dd HH:mm:ss)
|
|
|
+ stampLocalSignedAt: function() {
|
|
|
+ var self = this
|
|
|
+ var now = new Date()
|
|
|
+ var pad = function(n) { return n < 10 ? '0' + n : '' + n }
|
|
|
+ var str = now.getFullYear() + '-' + pad(now.getMonth() + 1) + '-' + pad(now.getDate()) +
|
|
|
+ ' ' + pad(now.getHours()) + ':' + pad(now.getMinutes()) + ':' + pad(now.getSeconds())
|
|
|
+ self.selectedMemberIds.forEach(function(mid) {
|
|
|
+ var key = String(mid)
|
|
|
+ if (self.memberFormMap[key]) self.$set(self.memberFormMap[key], 'signedAt', str)
|
|
|
+ })
|
|
|
+ },
|
|
|
|
|
|
// ===== 方案生成与编辑 (保持原有逻辑) =====
|
|
|
generatePlan: function() {
|
|
|
@@ -1777,6 +1842,32 @@ selectedMembers: function() {
|
|
|
color: #F97316;
|
|
|
margin-bottom: 12rpx;
|
|
|
}
|
|
|
+.confirm-member-head {
|
|
|
+ display: flex;
|
|
|
+ align-items: center;
|
|
|
+ justify-content: space-between;
|
|
|
+ margin-bottom: 12rpx;
|
|
|
+}
|
|
|
+.confirm-member-head .confirm-member-name {
|
|
|
+ margin-bottom: 0;
|
|
|
+}
|
|
|
+.confirm-member-signed {
|
|
|
+ font-size: calc(22rpx * var(--font-scale, 1));
|
|
|
+ color: #67c23a;
|
|
|
+}
|
|
|
+.confirm-extra-block {
|
|
|
+ border-top: 1rpx dashed #E5E5E5;
|
|
|
+ margin-top: 8rpx;
|
|
|
+ padding-top: 4rpx;
|
|
|
+}
|
|
|
+.confirm-toggle {
|
|
|
+ padding: 12rpx 0 4rpx;
|
|
|
+ text-align: center;
|
|
|
+}
|
|
|
+.confirm-toggle-text {
|
|
|
+ font-size: calc(24rpx * var(--font-scale, 1));
|
|
|
+ color: #667eea;
|
|
|
+}
|
|
|
.confirm-summary-row {
|
|
|
display: flex;
|
|
|
font-size: calc(24rpx * var(--font-scale, 1));
|