|
@@ -1,17 +1,10 @@
|
|
|
<template>
|
|
<template>
|
|
|
<view class="plan-page">
|
|
<view class="plan-page">
|
|
|
- <!-- 顶部导航 -->
|
|
|
|
|
- <view class="nav-bar">
|
|
|
|
|
- <text class="nav-back" @click="goBack">\ue601 返回</text>
|
|
|
|
|
- <text class="nav-title">方案制定</text>
|
|
|
|
|
- <view class="nav-placeholder"></view>
|
|
|
|
|
- </view>
|
|
|
|
|
-
|
|
|
|
|
<!-- 步骤指示器 -->
|
|
<!-- 步骤指示器 -->
|
|
|
<view class="steps-bar">
|
|
<view class="steps-bar">
|
|
|
<view class="step" :class="{ active: step >= 1, done: step > 1 }">
|
|
<view class="step" :class="{ active: step >= 1, done: step > 1 }">
|
|
|
<text class="step-num">1</text>
|
|
<text class="step-num">1</text>
|
|
|
- <text class="step-label">选报告</text>
|
|
|
|
|
|
|
+ <text class="step-label">选人</text>
|
|
|
</view>
|
|
</view>
|
|
|
<view class="step-line" :class="{ done: step > 1 }"></view>
|
|
<view class="step-line" :class="{ done: step > 1 }"></view>
|
|
|
<view class="step" :class="{ active: step >= 2, done: step > 2 }">
|
|
<view class="step" :class="{ active: step >= 2, done: step > 2 }">
|
|
@@ -25,36 +18,30 @@
|
|
|
</view>
|
|
</view>
|
|
|
</view>
|
|
</view>
|
|
|
|
|
|
|
|
- <!-- Step 1: 报告选择 -->
|
|
|
|
|
|
|
+ <!-- Step 1: 选择家庭成员 -->
|
|
|
<view class="section" v-if="step <= 2">
|
|
<view class="section" v-if="step <= 2">
|
|
|
- <view class="section-title">选择参考报告</view>
|
|
|
|
|
- <view class="hint-text">可多选,支持其他家人的报告</view>
|
|
|
|
|
- <view class="report-list">
|
|
|
|
|
|
|
+ <view class="section-title">选择家庭成员</view>
|
|
|
|
|
+ <view class="hint-text">选择方案针对的家庭成员(可多选)</view>
|
|
|
|
|
+ <view class="member-list">
|
|
|
<view
|
|
<view
|
|
|
- v-for="(r, idx) in allReports"
|
|
|
|
|
- :key="idx"
|
|
|
|
|
- class="report-card"
|
|
|
|
|
- :class="{ active: selectedReportIds.indexOf(r.id) >= 0 }"
|
|
|
|
|
- @click="toggleReport(r.id)"
|
|
|
|
|
|
|
+ v-for="(m, idx) in executors"
|
|
|
|
|
+ :key="m.memberId || idx"
|
|
|
|
|
+ class="member-card"
|
|
|
|
|
+ :class="{ active: selectedMemberIds.indexOf(m.memberId) >= 0 }"
|
|
|
|
|
+ @click="toggleMember(m.memberId)"
|
|
|
>
|
|
>
|
|
|
- <view class="report-card-left">
|
|
|
|
|
- <text class="report-card-icon">{{ r.reportType === 'gut_flora' ? '🦠' : '🩺' }}</text>
|
|
|
|
|
- <view class="report-card-info">
|
|
|
|
|
- <text class="report-card-name">{{ r.memberName || '未绑定' }}</text>
|
|
|
|
|
- <text class="report-card-type">{{ r.reportType === 'gut_flora' ? '菌群检测' : '体检报告' }}</text>
|
|
|
|
|
- </view>
|
|
|
|
|
- </view>
|
|
|
|
|
- <view class="report-card-right">
|
|
|
|
|
- <text class="report-card-date">{{ formatDate(r.reportDate) }}</text>
|
|
|
|
|
- <text class="report-check" v-if="selectedReportIds.indexOf(r.id) >= 0">✓</text>
|
|
|
|
|
|
|
+ <view class="member-card-left">
|
|
|
|
|
+ <view class="member-avatar">{{ m.name.charAt(0) }}</view>
|
|
|
|
|
+ <text class="member-card-name">{{ m.name }}</text>
|
|
|
</view>
|
|
</view>
|
|
|
|
|
+ <view class="member-check" v-if="selectedMemberIds.indexOf(m.memberId) >= 0">✓</view>
|
|
|
</view>
|
|
</view>
|
|
|
- <view v-if="allReports.length === 0" class="empty-state">
|
|
|
|
|
- <text class="empty-icon">📋</text>
|
|
|
|
|
- <text class="empty-text">暂无健康报告</text>
|
|
|
|
|
|
|
+ <view v-if="executors.length === 0" class="empty-state">
|
|
|
|
|
+ <text class="empty-icon">👨👩👧👦</text>
|
|
|
|
|
+ <text class="empty-text">暂无家庭成员</text>
|
|
|
</view>
|
|
</view>
|
|
|
</view>
|
|
</view>
|
|
|
- <button class="btn-next" :disabled="selectedReportIds.length === 0 || loading" @click="step = 2">
|
|
|
|
|
|
|
+ <button class="btn-next" :disabled="selectedMemberIds.length === 0 || loading" @click="step = 2">
|
|
|
{{ loading ? '生成中...' : '下一步' }}
|
|
{{ loading ? '生成中...' : '下一步' }}
|
|
|
</button>
|
|
</button>
|
|
|
</view>
|
|
</view>
|
|
@@ -82,7 +69,7 @@
|
|
|
{{ loading ? '正在生成方案...' : '生成方案' }}
|
|
{{ loading ? '正在生成方案...' : '生成方案' }}
|
|
|
</button>
|
|
</button>
|
|
|
</view>
|
|
</view>
|
|
|
- <view class="back-link" @click="step = 1">\ue601 返回选择报告</view>
|
|
|
|
|
|
|
+ <view class="back-link" @click="step = 1">← 返回选择成员</view>
|
|
|
</view>
|
|
</view>
|
|
|
|
|
|
|
|
<!-- Step 3: 方案 & 任务 -->
|
|
<!-- Step 3: 方案 & 任务 -->
|
|
@@ -141,7 +128,7 @@
|
|
|
确认并生成任务单
|
|
确认并生成任务单
|
|
|
</button>
|
|
</button>
|
|
|
</view>
|
|
</view>
|
|
|
- <view class="back-link" @click="step = 2">\ue601 返回修改需求</view>
|
|
|
|
|
|
|
+ <view class="back-link" @click="step = 2">← 返回修改需求</view>
|
|
|
</view>
|
|
</view>
|
|
|
|
|
|
|
|
<!-- 成功 -->
|
|
<!-- 成功 -->
|
|
@@ -157,17 +144,16 @@
|
|
|
</template>
|
|
</template>
|
|
|
|
|
|
|
|
<script>
|
|
<script>
|
|
|
-import { getFamilyReports, getFamilyMembers, getHealthStatus, getDietPreferences, aiSendMessage, createTask } from '../../utils/api'
|
|
|
|
|
|
|
+import { getFamilyMembers, getHealthStatus, getDietPreferences, aiSendMessage, createTask } from '../../utils/api'
|
|
|
import { parseDate } from '../../utils/format'
|
|
import { parseDate } from '../../utils/format'
|
|
|
|
|
|
|
|
export default {
|
|
export default {
|
|
|
data() {
|
|
data() {
|
|
|
return {
|
|
return {
|
|
|
step: 1,
|
|
step: 1,
|
|
|
- initialReportIds: [],
|
|
|
|
|
|
|
+ initialMemberIds: [],
|
|
|
subjectId: '',
|
|
subjectId: '',
|
|
|
- allReports: [],
|
|
|
|
|
- selectedReportIds: [],
|
|
|
|
|
|
|
+ selectedMemberIds: [],
|
|
|
executors: [],
|
|
executors: [],
|
|
|
userGoal: '',
|
|
userGoal: '',
|
|
|
loading: false,
|
|
loading: false,
|
|
@@ -181,19 +167,18 @@ export default {
|
|
|
},
|
|
},
|
|
|
computed: {
|
|
computed: {
|
|
|
canGenerate: function() {
|
|
canGenerate: function() {
|
|
|
- return this.selectedReportIds.length > 0 && this.userGoal && this.userGoal.trim().length > 0 && !this.loading
|
|
|
|
|
|
|
+ return this.selectedMemberIds.length > 0 && this.userGoal && this.userGoal.trim().length > 0 && !this.loading
|
|
|
},
|
|
},
|
|
|
canConfirmTasks: function() {
|
|
canConfirmTasks: function() {
|
|
|
return this.parsedTasks.length > 0 && this.parsedTasks.every(function(t) { return t.executorId })
|
|
return this.parsedTasks.length > 0 && this.parsedTasks.every(function(t) { return t.executorId })
|
|
|
}
|
|
}
|
|
|
},
|
|
},
|
|
|
onLoad: function(options) {
|
|
onLoad: function(options) {
|
|
|
- if (options.initialReportIds) {
|
|
|
|
|
- this.initialReportIds = options.initialReportIds.split(',').map(Number)
|
|
|
|
|
- this.selectedReportIds = this.initialReportIds.slice()
|
|
|
|
|
|
|
+ if (options.initialMemberIds) {
|
|
|
|
|
+ this.initialMemberIds = options.initialMemberIds.split(',')
|
|
|
|
|
+ this.selectedMemberIds = this.initialMemberIds.slice()
|
|
|
}
|
|
}
|
|
|
this.subjectId = options.subjectId || ''
|
|
this.subjectId = options.subjectId || ''
|
|
|
- this.loadFamilyReports()
|
|
|
|
|
this.loadExecutors()
|
|
this.loadExecutors()
|
|
|
this.loadHealthContext()
|
|
this.loadHealthContext()
|
|
|
},
|
|
},
|
|
@@ -201,37 +186,6 @@ export default {
|
|
|
this.loadHealthContext()
|
|
this.loadHealthContext()
|
|
|
},
|
|
},
|
|
|
methods: {
|
|
methods: {
|
|
|
- formatDate: function(ts) {
|
|
|
|
|
- if (!ts) return '--'
|
|
|
|
|
- var d = new Date(ts)
|
|
|
|
|
- if (isNaN(d.getTime())) return '--'
|
|
|
|
|
- var mm = String(d.getMonth() + 1).padStart(2, '0')
|
|
|
|
|
- var dd = String(d.getDate()).padStart(2, '0')
|
|
|
|
|
- return d.getFullYear() + '-' + mm + '-' + dd
|
|
|
|
|
- },
|
|
|
|
|
- loadFamilyReports: function() {
|
|
|
|
|
- var self = this
|
|
|
|
|
- getFamilyReports().then(function(res) {
|
|
|
|
|
- if (res && res.code === 200 && res.data) {
|
|
|
|
|
- var reports = res.data
|
|
|
|
|
- reports.forEach(function(r) {
|
|
|
|
|
- if (!r.memberName) {
|
|
|
|
|
- var mid = r.subjectId || r.userId
|
|
|
|
|
- self.executors.forEach(function(e) {
|
|
|
|
|
- if ((e.memberId || e.id) === mid) r.memberName = e.name || '成员'
|
|
|
|
|
- })
|
|
|
|
|
- if (!r.memberName) r.memberName = r.personName || '未知'
|
|
|
|
|
- }
|
|
|
|
|
- })
|
|
|
|
|
- self.allReports = reports
|
|
|
|
|
- if (self.initialReportIds.length > 0) {
|
|
|
|
|
- self.selectedReportIds = self.initialReportIds.filter(function(id) {
|
|
|
|
|
- return reports.some(function(r) { return r.id === id })
|
|
|
|
|
- })
|
|
|
|
|
- }
|
|
|
|
|
- }
|
|
|
|
|
- }).catch(function() {})
|
|
|
|
|
- },
|
|
|
|
|
loadExecutors: function() {
|
|
loadExecutors: function() {
|
|
|
var self = this
|
|
var self = this
|
|
|
getFamilyMembers().then(function(res) {
|
|
getFamilyMembers().then(function(res) {
|
|
@@ -258,10 +212,10 @@ export default {
|
|
|
}
|
|
}
|
|
|
}).catch(function() { self.dietPrefs = null })
|
|
}).catch(function() { self.dietPrefs = null })
|
|
|
},
|
|
},
|
|
|
- toggleReport: function(reportId) {
|
|
|
|
|
- var idx = this.selectedReportIds.indexOf(reportId)
|
|
|
|
|
- if (idx >= 0) this.selectedReportIds.splice(idx, 1)
|
|
|
|
|
- else this.selectedReportIds.push(reportId)
|
|
|
|
|
|
|
+ toggleMember: function(memberId) {
|
|
|
|
|
+ var idx = this.selectedMemberIds.indexOf(memberId)
|
|
|
|
|
+ if (idx >= 0) this.selectedMemberIds.splice(idx, 1)
|
|
|
|
|
+ else this.selectedMemberIds.push(memberId)
|
|
|
},
|
|
},
|
|
|
generatePlan: function() {
|
|
generatePlan: function() {
|
|
|
var self = this
|
|
var self = this
|
|
@@ -312,8 +266,8 @@ export default {
|
|
|
doGeneratePlan: function() {
|
|
doGeneratePlan: function() {
|
|
|
var self = this
|
|
var self = this
|
|
|
self.loading = true
|
|
self.loading = true
|
|
|
- var reportIdsStr = self.selectedReportIds.join(',')
|
|
|
|
|
- var sendData = { query: self.userGoal.trim(), reportId: reportIdsStr }
|
|
|
|
|
|
|
+ var memberIdsStr = self.selectedMemberIds.join(',')
|
|
|
|
|
+ var sendData = { query: self.userGoal.trim(), subjectIds: memberIdsStr }
|
|
|
if (self.healthStatus) sendData.healthStatus = JSON.stringify(self.healthStatus)
|
|
if (self.healthStatus) sendData.healthStatus = JSON.stringify(self.healthStatus)
|
|
|
if (self.dietPrefs) sendData.dietPrefs = JSON.stringify(self.dietPrefs)
|
|
if (self.dietPrefs) sendData.dietPrefs = JSON.stringify(self.dietPrefs)
|
|
|
aiSendMessage(sendData).then(function(res) {
|
|
aiSendMessage(sendData).then(function(res) {
|
|
@@ -426,30 +380,6 @@ export default {
|
|
|
padding-bottom: 40rpx;
|
|
padding-bottom: 40rpx;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
-/* 导航栏 */
|
|
|
|
|
-.nav-bar {
|
|
|
|
|
- display: flex;
|
|
|
|
|
- align-items: center;
|
|
|
|
|
- justify-content: space-between;
|
|
|
|
|
- height: 88rpx;
|
|
|
|
|
- padding: 0 30rpx;
|
|
|
|
|
- background: #fff;
|
|
|
|
|
- border-bottom: 1rpx solid #eee;
|
|
|
|
|
- position: sticky;
|
|
|
|
|
- top: 0;
|
|
|
|
|
- z-index: 10;
|
|
|
|
|
-}
|
|
|
|
|
-.nav-back {
|
|
|
|
|
- font-size: 32rpx;
|
|
|
|
|
- color: #F97316;
|
|
|
|
|
-}
|
|
|
|
|
-.nav-title {
|
|
|
|
|
- font-size: 34rpx;
|
|
|
|
|
- font-weight: bold;
|
|
|
|
|
- color: #333;
|
|
|
|
|
-}
|
|
|
|
|
-.nav-placeholder { width: 80rpx; }
|
|
|
|
|
-
|
|
|
|
|
/* 步骤条 */
|
|
/* 步骤条 */
|
|
|
.steps-bar {
|
|
.steps-bar {
|
|
|
display: flex;
|
|
display: flex;
|