Commit a8babdb1 authored by spc's avatar spc

feeding

parent bbc2edb5
......@@ -42,14 +42,14 @@
<view v-for="(day, index) in chartData" :key="index" class="chart-bar-wrapper" @click="onBarClick(day)">
<view class="chart-bar">
<view v-for="(typeData, typeIndex) in getBarSegments(day)" :key="typeIndex" class="bar-segment" :style="{
height: `${typeData.height}%`,
backgroundColor: typeData.color
height: `${typeData.height}%`,
backgroundColor: typeData.color
}"></view>
</view>
<view class="bar-count" v-if="day.dateString === selectedDate && day.totalCount > 0">
{{ day.totalCount }}
</view>
<view class="bar-date">{{ day.date }}</view>
<view class="bar-date" :class="{ 'selected': day.dateString === selectedDate }">{{ day.date }}</view>
<!-- 选中背景图 -->
<image v-if="day.dateString === selectedDate" :src="feedingAnalysisRes.icon_sel_tag_bg"
class="selected-bg" />
......@@ -59,13 +59,13 @@
<view class="chart-nav-right" @click="nextWeek">
<image :src="feedingAnalysisRes.icon_r_arrow" class="nav-arrow" />
</view>
</view>
</view>
</view>
<view class="gap-bg"></view>
<!-- 宝宝年龄 -->
<view class="baby-age">
<text>宝宝 {{ calculateBabyAge(babyInfo.birthday) }} </text>
<!-- 宝宝年龄 -->
<view class="baby-age">
<text>宝宝 {{ userStore.babyInfo?.babyAge || '0天' }} </text>
</view>
<!-- 喂养记录列表 -->
......@@ -97,38 +97,38 @@
<!-- 如果没有 foodDetails,则显示原有字段 -->
<view v-else>
<!-- 母乳亲喂:显示左右时间,时间加粗 -->
<view v-if="record.type === '母乳亲喂' && (record.leftDuration || record.rightDuration)"
class="duration-info">
<view v-if="record.leftDuration" class="duration-text">
<text class="duration-label"></text>
<text class="duration-time">{{ record.leftDuration }}</text>
<!-- 母乳亲喂:显示左右时间,时间加粗 -->
<view v-if="record.type === '母乳亲喂' && (record.leftDuration || record.rightDuration)"
class="duration-info">
<view v-if="record.leftDuration" class="duration-text">
<text class="duration-label"></text>
<text class="duration-time">{{ record.leftDuration }}</text>
</view>
<view v-if="record.rightDuration" class="duration-text">
<text class="duration-label"></text>
<text class="duration-time">{{ record.rightDuration }}</text>
</view>
</view>
<view v-if="record.rightDuration" class="duration-text">
<text class="duration-label"></text>
<text class="duration-time">{{ record.rightDuration }}</text>
</view>
</view>
<!-- 母乳瓶喂:显示总乳量 -->
<view v-if="record.type === '母乳瓶喂' && record.amount" class="amount-info">
<view class="amount-text">
<text class="amount-label">总乳量</text>
<text class="amount-value">{{ record.amount }}</text>
<!-- 母乳瓶喂:显示总乳量 -->
<view v-if="record.type === '母乳瓶喂' && record.amount" class="amount-info">
<view class="amount-text">
<text class="amount-label">总乳量</text>
<text class="amount-value">{{ record.amount }}</text>
</view>
</view>
</view>
<!-- 奶粉喂养:显示总奶量 -->
<view v-if="record.type === '奶粉喂养' && record.amount" class="amount-info">
<view class="amount-text">
<text class="amount-label">总奶量</text>
<text class="amount-value">{{ record.amount }}</text>
<!-- 奶粉喂养:显示总奶量 -->
<view v-if="record.type === '奶粉喂养' && record.amount" class="amount-info">
<view class="amount-text">
<text class="amount-label">总奶量</text>
<text class="amount-value">{{ record.amount }}</text>
</view>
</view>
</view>
<!-- 辅食:显示内容,超出显示... -->
<view v-if="record.type === '辅食' && record.content" class="content-info">
<view class="content-text">{{ record.content }}</view>
<!-- 辅食:显示内容,超出显示... -->
<view v-if="record.type === '辅食' && record.content" class="content-info">
<view class="content-text">{{ record.content }}</view>
</view>
</view>
</view>
......@@ -144,29 +144,28 @@
<!-- 编辑记录弹窗 -->
<view class="popup-mask" v-if="showEditPopup" @click="closeEditPopup" @touchmove.prevent>
<view class="popup-content" @click.stop @touchmove.stop>
<view class="popup-title">修改喂养记录</view>
<view class="popup-title">确认修改内容</view>
<view class="form-item">
<text class="label">时间:</text>
<text class="label">喂养时间</text>
<picker mode="time" :value="editForm.time" @change="onEditTimeChange">
<view class="picker">{{ editForm.time || '请选择时间' }}</view>
</picker>
</view>
<view class="form-item">
<text class="label">类型:</text>
<text class="label">喂养方式</text>
<picker :range="feedingTypes" @change="onEditTypeChange">
<view class="picker">{{ editForm.type || '请选择类型' }}</view>
</picker>
</view>
<view class="form-item">
<text class="label">喂养详情</text>
<text class="label">喂养详情</text>
<view class="input-container">
<input class="input" v-model="editForm.content" placeholder="请输入具体内容" maxlength="20" />
<text class="char-count">{{ editForm.content.length }}/20</text>
<input class="input" v-model="editForm.content" :placeholder="getEditFormPlaceholder()" maxlength="20" />
</view>
</view>
<view class="popup-buttons">
<button class="cancel-btn" @click="closeEditPopup">取消</button>
<button class="confirm-btn" @click="saveEditRecord">保存</button>
<image :src="feedingAnalysisRes.icon_change_btn_cancel" class="cancel-btn" @click="closeEditPopup" />
<image :src="feedingAnalysisRes.icon_change_btn_confirm" class="confirm-btn" @click="saveEditRecord" />
</view>
</view>
</view>
......@@ -176,7 +175,7 @@
import { ref, computed, onMounted, onUnmounted, watch, nextTick, getCurrentInstance } from 'vue'
import { onLoad, onShow } from '@dcloudio/uni-app'
import { feedingRecordsStatisticsPeriod, feedingRecordsByDate, feedingRecords as feedingRecordsAPI } from '@/api/feeding.js'
import { useFeedStore } from '@/stores/feed.js'
import { useUserStore } from '@/stores/user.js'
// API 集成说明:
// 1. 使用 /c/feeding/statistics/period GET 方法查询统计图表数据
......@@ -223,6 +222,9 @@ const feedingAnalysisRes = {
icon_r_arrow: $baseUrl + `feedingAnalysis/${version}/icon_r_arrow.png`,
icon_sel_tag_bg: $baseUrl + `feedingAnalysis/${version}/icon_sel_tag_bg.png`,
icon_change_btn_confirm: $baseUrl + `feedingRecord/${version}/icon_change_btn_confirm.png`,
icon_change_btn_cancel: $baseUrl + `feedingRecord/${version}/icon_change_btn_cancel.png`,
}
......@@ -241,10 +243,11 @@ const selectedDate = ref(formatDateString(new Date())) // 当前选中的日期
const chartData = ref([])
// 全局状态管理
const feedStore = useFeedStore()
const userStore = useUserStore()
const babyId = computed(() => userStore.babyInfo?.content?.id)
// 计算属性 - 获取宝宝信息
const babyInfo = computed(() => feedStore.getCurrentBaby())
const babyInfo = computed(() => userStore.babyInfo?.content)
// 修改记录相关状态
const showEditPopup = ref(false)
......@@ -331,14 +334,14 @@ function getRecordIconClass(type) {
// API 调用函数
async function loadStatisticsPeriod(startDate, endDate) {
const cacheKey = `${startDate}_${endDate}_${feedStore.getCurrentBabyId()}`
const cacheKey = `${startDate}_${endDate}_${babyId.value}`
// 避免重复请求
if (loadingStatistics.value.has(cacheKey)) {
console.log('该时间段统计数据正在加载中,跳过重复请求:', cacheKey)
return
}
// 检查缓存
const cachedData = statisticsCache.value.get(cacheKey)
if (cachedData && Date.now() - cachedData.timestamp < 10 * 60 * 1000) { // 10分钟缓存
......@@ -346,7 +349,7 @@ async function loadStatisticsPeriod(startDate, endDate) {
apiStatistics.value[cacheKey] = cachedData.data
return
}
try {
const startTime = Date.now()
loadingStatistics.value.add(cacheKey)
......@@ -354,39 +357,39 @@ async function loadStatisticsPeriod(startDate, endDate) {
if (loadingStatistics.value.size === 1) {
isLoading.value = true
}
// 添加超时处理
const timeoutPromise = new Promise((_, reject) => {
setTimeout(() => reject(new Error('请求超时')), 10000) // 10秒超时
})
const apiPromise = feedingRecordsStatisticsPeriod({
babyId: feedStore.getCurrentBabyId(),
babyId: babyId.value,
sdate: startDate,
edate: endDate
})
// 使用 mock 数据或真实 API
const response = await Promise.race([apiPromise, timeoutPromise])
if (DEBUG_API) {
console.log('获取统计数据:', { startDate, endDate }, response)
console.log('统计数据API返回数据结构:', JSON.stringify(response, null, 2))
}
// 检查响应状态
if (response && response.code && response.code !== '000000') {
throw new Error(`API返回错误: ${response.message || '未知错误'}`)
}
if (response && response.data) {
// 验证数据格式
if (!Array.isArray(response.data)) {
console.error('统计数据API返回的数据格式不正确,期望数组:', response.data)
return
}
// 转换API数据格式为页面需要的格式
const statistics = response.data.map(item => {
// 验证项目格式
......@@ -394,7 +397,7 @@ async function loadStatisticsPeriod(startDate, endDate) {
console.warn('跳过无效的统计项目:', item)
return null
}
return {
date: item.feedDate,
dateString: item.feedDate,
......@@ -407,21 +410,21 @@ async function loadStatisticsPeriod(startDate, endDate) {
}
}
}).filter(item => item !== null) // 过滤掉无效项目
apiStatistics.value[cacheKey] = statistics
// 添加到缓存
statisticsCache.value.set(cacheKey, {
data: statistics,
timestamp: Date.now()
})
// 记录性能
const endTime = Date.now()
console.log(`获取统计数据耗时: ${endTime - startTime}ms`)
} else {
console.log('统计数据API返回空数据')
// 缓存空数据
statisticsCache.value.set(cacheKey, {
data: [],
......@@ -430,7 +433,7 @@ async function loadStatisticsPeriod(startDate, endDate) {
}
} catch (error) {
handleApiError(error, '获取统计数据')
// 简单的重试机制(最多重试1次)
if (!loadingStatistics.value.has(`${cacheKey}_retry`)) {
console.log('尝试重试获取统计数据...')
......@@ -440,7 +443,7 @@ async function loadStatisticsPeriod(startDate, endDate) {
}, 2000) // 2秒后重试
return
}
// 如果API失败,使用本地数据作为fallback
console.warn('API获取统计数据失败,使用本地数据作为fallback')
} finally {
......@@ -458,7 +461,7 @@ async function loadRecordsByDate(date) {
console.log('该日期记录正在加载中,跳过重复请求:', date)
return
}
// 检查缓存
const cacheKey = `${date}_${babyInfo.value.id}`
const cachedData = recordsCache.value.get(cacheKey)
......@@ -467,7 +470,7 @@ async function loadRecordsByDate(date) {
apiRecords.value[date] = cachedData.data
return
}
try {
const startTime = Date.now()
loadingRecords.value.add(date)
......@@ -475,36 +478,36 @@ async function loadRecordsByDate(date) {
if (loadingRecords.value.size === 1) {
isLoading.value = true
}
// Mock 数据模拟
const mockResponse = {
code: '000000',
data: [] // 删除所有 feedingRecords.value[date] || []
}
// 添加超时处理
const timeoutPromise = new Promise((_, reject) => {
setTimeout(() => reject(new Error('请求超时')), 10000) // 10秒超时
})
const apiPromise = feedingRecordsByDate({
babyId: feedStore.getCurrentBabyId(),
babyId: babyId.value,
date: date
})
// 使用 mock 数据或真实 API
const response = await Promise.race([apiPromise, timeoutPromise])
if (DEBUG_API) {
console.log('获取指定日期记录:', date, response)
console.log('记录API返回数据结构:', JSON.stringify(response, null, 2))
}
// 检查响应状态
if (response && response.code && response.code !== '000000') {
throw new Error(`API返回错误: ${response.message || '未知错误'}`)
}
if (response && response.data) {
// 验证数据格式
if (!Array.isArray(response.data)) {
......@@ -512,7 +515,7 @@ async function loadRecordsByDate(date) {
apiRecords.value[date] = []
return
}
// 转换API数据格式为页面需要的格式
const records = response.data.map(record => {
// 验证记录格式
......@@ -520,7 +523,7 @@ async function loadRecordsByDate(date) {
console.warn('跳过无效的记录:', record)
return null
}
return {
id: record.id, // 保留原始记录ID,用于修改时传递
recordId: record.recordId, // 添加recordId字段用于编辑
......@@ -533,25 +536,25 @@ async function loadRecordsByDate(date) {
foodDetails: record.foodDetails || '' // 添加foodDetails字段
}
}).filter(record => record !== null) // 过滤掉无效记录
// 按时间排序
records.sort((a, b) => a.time.localeCompare(b.time))
apiRecords.value[date] = records
// 添加到缓存
recordsCache.value.set(cacheKey, {
data: records,
timestamp: Date.now()
})
// 记录性能
const endTime = Date.now()
console.log(`获取记录数据耗时: ${endTime - startTime}ms`)
} else {
apiRecords.value[date] = []
console.log('记录API返回空数据')
// 缓存空数据
recordsCache.value.set(cacheKey, {
data: [],
......@@ -560,7 +563,7 @@ async function loadRecordsByDate(date) {
}
} catch (error) {
handleApiError(error, '获取指定日期记录')
// 简单的重试机制(最多重试1次)
if (!loadingRecords.value.has(`${date}_retry`)) {
console.log('尝试重试获取记录数据...')
......@@ -570,7 +573,7 @@ async function loadRecordsByDate(date) {
}, 2000) // 2秒后重试
return
}
// 如果API失败,使用本地数据作为fallback
console.warn('API获取记录失败,使用本地数据作为fallback')
} finally {
......@@ -585,7 +588,7 @@ async function loadRecordsByDate(date) {
// 统一错误处理函数
function handleApiError(error, context) {
console.error(`${context} 失败:`, error)
// 检查网络状态
uni.getNetworkType({
success: (res) => {
......@@ -594,7 +597,7 @@ function handleApiError(error, context) {
}
}
})
// 根据错误类型提供不同的处理建议
if (error.message && error.message.includes('超时')) {
console.warn('请求超时,可能是网络问题')
......@@ -608,7 +611,7 @@ function handleApiError(error, context) {
// 工具函数
function formatTimeFromTimestamp(timestamp) {
if (!timestamp) return ''
let date
// 处理不同的时间戳格式
if (typeof timestamp === 'string') {
......@@ -626,13 +629,13 @@ function formatTimeFromTimestamp(timestamp) {
} else {
date = new Date(timestamp)
}
// 检查日期是否有效
if (isNaN(date.getTime())) {
console.error('无效的时间戳:', timestamp)
return ''
}
const hours = String(date.getHours()).padStart(2, '0')
const minutes = String(date.getMinutes()).padStart(2, '0')
return `${hours}:${minutes}`
......@@ -692,11 +695,11 @@ function calculateBabyAge(birthday) {
const today = new Date()
const diffTime = Math.abs(today - birthDate)
const diffDays = Math.ceil(diffTime / (1000 * 60 * 60 * 24))
const years = Math.floor(diffDays / 365)
const months = Math.floor((diffDays % 365) / 30)
const days = diffDays % 30
if (years > 0) {
return `${years}${months}个月${days}天`
} else if (months > 0) {
......@@ -709,7 +712,7 @@ function calculateBabyAge(birthday) {
// 编辑记录
function editRecord(index) {
console.log('编辑记录:', index)
const record = todayRecords.value[index]
if (!record) {
uni.showToast({
......@@ -718,23 +721,42 @@ function editRecord(index) {
})
return
}
// 根据记录类型设置不同的字段
let content = ''
if (record.type === '母乳亲喂') {
// 母乳亲喂:优先显示 foodDetails,如果没有则从左右时间构建
if (record.foodDetails) {
content = record.foodDetails
} else {
const leftTime = record.leftDuration || ''
const rightTime = record.rightDuration || ''
content = `${leftTime} ${rightTime}`.trim()
}
} else if (record.type === '母乳瓶喂') {
// 母乳瓶喂:优先显示 foodDetails,如果没有则显示 amount
content = record.foodDetails || record.amount || ''
} else if (record.type === '奶粉喂养') {
// 奶粉喂养:优先显示 foodDetails,如果没有则显示 amount
content = record.foodDetails || record.amount || ''
} else if (record.type === '辅食') {
// 辅食:显示食物详情
content = record.foodDetails || record.content || ''
}
// 设置编辑表单数据
editForm.value = {
time: record.time || getCurrentTime(), // 使用记录的原始时间,如果没有则使用当前时间
type: record.type || '',
content: record.foodDetails || record.content || '', // 优先使用foodDetails
leftDuration: record.leftDuration || '',
rightDuration: record.rightDuration || '',
amount: record.amount || ''
content: content
}
// 保存当前编辑的记录
editingRecord.value = {
index,
record
}
// 显示编辑弹窗
showEditPopup.value = true
}
......@@ -749,18 +771,18 @@ function generateWeekData(weekOffset = 0, targetDate = null) {
const data = []
const baseDate = new Date() // 使用当前日期作为基准
baseDate.setDate(baseDate.getDate() + weekOffset * 7)
// 计算当前周的开始和结束日期
const startDate = new Date(baseDate)
startDate.setDate(baseDate.getDate() - baseDate.getDay()) // 设置为周日
const endDate = new Date(startDate)
endDate.setDate(startDate.getDate() + 6) // 设置为周六
const startDateString = formatDateString(startDate)
const endDateString = formatDateString(endDate)
// 获取统计数据的缓存键
const cacheKey = `${startDateString}_${endDateString}_${feedStore.getCurrentBabyId()}`
const cacheKey = `${startDateString}_${endDateString}_${babyId.value}`
const statisticsData = apiStatistics.value[cacheKey] || []
// 确定要选中的日期
......@@ -775,12 +797,12 @@ function generateWeekData(weekOffset = 0, targetDate = null) {
activeDate = startDateString
}
}
for (let i = 0; i < 7; i++) {
const date = new Date(startDate)
date.setDate(startDate.getDate() + i)
const dateString = formatDateString(date)
// 从统计数据中查找对应日期的数据
const statisticsItem = statisticsData.find(item => item.dateString === dateString)
......@@ -799,15 +821,15 @@ function generateWeekData(weekOffset = 0, targetDate = null) {
dateString,
totalCount: 0,
typeCounts: {
'母乳亲喂': 0,
'母乳瓶喂': 0,
'奶粉喂养': 0,
'辅食': 0
}
'母乳亲喂': 0,
'母乳瓶喂': 0,
'奶粉喂养': 0,
'辅食': 0
}
})
}
}
return data
}
......@@ -907,10 +929,7 @@ function closeEditPopup() {
editForm.value = {
time: '',
type: '',
content: '',
leftDuration: '',
rightDuration: '',
amount: ''
content: ''
}
}
......@@ -931,7 +950,7 @@ function saveEditRecord() {
})
return
}
// 验证喂养详情(最多20字)
if (editForm.value.content && editForm.value.content.length > 20) {
uni.showToast({
......@@ -940,7 +959,7 @@ function saveEditRecord() {
})
return
}
if (!editingRecord.value) {
uni.showToast({
title: '编辑记录不存在',
......@@ -948,29 +967,42 @@ function saveEditRecord() {
})
return
}
// 构建API请求数据
const { index, record } = editingRecord.value
const apiData = {
// 根据记录类型处理不同的数据
let apiData = {
recordId: record.recordId,
babyId: feedStore.getCurrentBabyId(),
babyId: babyId.value,
recordTime: formatDateTimeString(selectedDate.value, editForm.value.time),
feedingType: getFeedingTypeId(editForm.value.type)
}
// 根据喂养类型添加相应字段
// 所有类型都使用 foodDetails 字段保存
apiData.foodDetails = editForm.value.content || ''
// 根据记录类型设置其他字段
if (editForm.value.type === '母乳亲喂') {
apiData.durationLeftSeconds = parseDurationToSeconds(editForm.value.leftDuration)
apiData.durationRightSeconds = parseDurationToSeconds(editForm.value.rightDuration)
// 母乳亲喂:解析时间(格式:时间1 时间2)
const content = editForm.value.content || ''
const timeParts = content.trim().split(/\s+/)
if (timeParts.length >= 1 && timeParts[0]) {
apiData.durationLeftSeconds = parseTimeToSeconds(timeParts[0])
}
if (timeParts.length >= 2 && timeParts[1]) {
apiData.durationRightSeconds = parseTimeToSeconds(timeParts[1])
}
} else if (editForm.value.type === '母乳瓶喂' || editForm.value.type === '奶粉喂养') {
apiData.volume = parseVolumeToNumber(editForm.value.amount)
// 母乳瓶喂和奶粉喂养:解析奶量
const content = editForm.value.content || ''
const volumeMatch = content.match(/(\d+)ml/)
if (volumeMatch) {
apiData.volume = parseInt(volumeMatch[1])
}
}
// 统一添加 foodDetails 字段
if (editForm.value.content) {
apiData.foodDetails = editForm.value.content
}
// 调用API保存修改
saveRecordToAPI(apiData, index)
}
......@@ -995,17 +1027,17 @@ async function saveRecordToAPI(apiData, index) {
uni.showLoading({
title: '保存中...'
})
const response = await feedingRecordsAPI(apiData)
if (response && response.code === '000000') {
uni.showToast({
title: '保存成功',
icon: 'success'
})
closeEditPopup()
// 清空缓存,确保获取最新数据
clearCache()
......@@ -1033,7 +1065,7 @@ async function saveRecordToAPI(apiData, index) {
function updateLocalRecord(index, formData) {
const dateKey = selectedDate.value
if (!dateKey) return
// 更新API数据
if (apiRecords.value[dateKey] && apiRecords.value[dateKey][index]) {
const record = apiRecords.value[dateKey][index]
......@@ -1044,7 +1076,7 @@ function updateLocalRecord(index, formData) {
record.rightDuration = formData.rightDuration
record.amount = formData.amount
}
// 更新本地数据
// 本地数据不再需要更新,因为API调用失败时,apiRecords.value[dateKey] 为空
}
......@@ -1053,7 +1085,7 @@ function updateLocalRecord(index, formData) {
async function selectDate(dateString) {
console.log('selectDate 被调用,日期:', dateString)
selectedDate.value = dateString
// 加载选中日期的记录
await loadRecordsByDate(dateString)
console.log('selectDate 完成,当前选中日期:', selectedDate.value)
......@@ -1093,7 +1125,11 @@ function getBarSegments(day) {
}
// 页面加载
onLoad(() => {
onLoad(async () => {
// 加载宝宝信息
await userStore.loadBabyInfo()
console.log('宝宝信息加载完成:', userStore.babyInfo)
updateChartData(false) // 初始化时使用默认选择
// 初始化API数据
initializeApiData()
......@@ -1125,24 +1161,32 @@ async function initializeChartData() {
// 初始化API数据
async function initializeApiData() {
console.log('初始化API数据...')
// 加载当前选中日期的记录
if (selectedDate.value) {
console.log('加载当前选中日期记录:', selectedDate.value)
await loadRecordsByDate(selectedDate.value)
}
console.log('API数据初始化完成')
}
// 页面挂载时初始化数据
onMounted(async () => {
// 加载宝宝信息
await userStore.loadBabyInfo()
console.log('宝宝信息加载完成:', userStore.babyInfo)
// 先加载统计数据,然后更新图表(updateChartData 中已经包含了加载记录的逻辑)
await initializeChartData()
})
// 页面显示时刷新数据
onShow(() => {
onShow(async () => {
// 加载宝宝信息
await userStore.loadBabyInfo()
console.log('宝宝信息加载完成:', userStore.babyInfo)
// 如果已经有选中日期,刷新当前日期的记录
if (selectedDate.value) {
loadRecordsByDate(selectedDate.value)
......@@ -1161,6 +1205,25 @@ function formatMonthString(date) {
return `${year}-${month}`
}
// 解析时间格式为秒数
function parseTimeToSeconds(timeString) {
if (!timeString) return 0
const parts = timeString.split(':')
if (parts.length === 2) {
const minutes = parseInt(parts[0], 10)
const seconds = parseInt(parts[1], 10)
return minutes * 60 + seconds
}
return 0
}
// 获取编辑表单的占位符
function getEditFormPlaceholder() {
return '输入具体内容'
}
// 清空缓存函数
function clearCache() {
console.log('清空缓存...')
......@@ -1183,7 +1246,7 @@ function testApiIntegration() {
console.log('=== 测试API集成 ===')
console.log('当前选中日期:', selectedDate.value)
console.log('当前周数:', currentWeek.value)
console.log('当前宝宝ID:', feedStore.getCurrentBabyId())
console.log('当前宝宝ID:', babyId.value)
console.log('API统计数据:', apiStatistics.value)
console.log('API记录数据:', apiRecords.value)
console.log('缓存状态:', {
......@@ -1340,18 +1403,18 @@ function testApiIntegration() {
box-sizing: border-box;
position: relative;
.chart-bar-wrapper {
display: flex;
flex-direction: column;
align-items: center;
flex: 1;
position: relative;
padding: 0 10rpx;
transition: all 0.3s ease;
.chart-bar-wrapper {
display: flex;
flex-direction: column;
align-items: center;
flex: 1;
position: relative;
padding: 0 10rpx;
transition: all 0.3s ease;
.chart-bar {
.chart-bar {
width: 77rpx;
height: 360rpx;
display: flex;
......@@ -1368,12 +1431,12 @@ function testApiIntegration() {
min-height: 10rpx;
transition: height 0.3s ease;
flex-shrink: 0;
// 如果只有一个段,整个柱子都有圆角
&:only-child {
border-radius: 8rpx !important;
}
// 多个段的情况
&:not(:only-child) {
......@@ -1382,13 +1445,13 @@ function testApiIntegration() {
border-top-left-radius: 8rpx !important;
border-top-right-radius: 8rpx !important;
}
// 最后一个段(顶部)有顶部圆角
&:last-child {
border-bottom-left-radius: 8rpx !important;
border-bottom-right-radius: 8rpx !important;
}
// 中间段没有圆角
&:not(:first-child):not(:last-child) {
border-radius: 0 !important;
......@@ -1418,6 +1481,10 @@ function testApiIntegration() {
position: relative;
z-index: 2;
pointer-events: none; // 确保不拦截点击事件
&.selected {
color: #1d1e25;
}
}
// 确保点击时没有任何背景色变化
......@@ -1453,18 +1520,19 @@ function testApiIntegration() {
margin-top: -43rpx;
border-radius: 30rpx 30rpx 0 0;
background: #ffffff;
}
}
.baby-age {
.baby-age {
text-align: left;
padding: 25rpx 0 0 40rpx;
background: #ffffff;
height: 80rpx;
text {
font-size: 26rpx;
color: #000000; // 黑色文字
font-weight: bold; // 加粗
text {
font-size: 26rpx;
color: #000000; // 黑色文字
font-weight: bold; // 加粗
line-height: 80rpx;
}
}
......@@ -1681,7 +1749,7 @@ function testApiIntegration() {
}
.popup-content {
background: #fff;
background: #f6f8fa;
width: 100%;
border-radius: 20rpx 20rpx 0 0;
padding: 40rpx 30rpx;
......@@ -1693,7 +1761,7 @@ function testApiIntegration() {
font-size: 36rpx;
font-weight: 600;
color: #333;
text-align: center;
text-align: left;
margin-bottom: 40rpx;
}
......@@ -1702,10 +1770,14 @@ function testApiIntegration() {
position: relative;
.label {
position: absolute;
left: 24rpx;
top: 50%;
transform: translateY(-50%);
font-size: 28rpx;
color: #333;
margin-bottom: 12rpx;
display: block;
z-index: 2;
pointer-events: none;
}
.input-container {
......@@ -1716,10 +1788,11 @@ function testApiIntegration() {
.picker,
.input {
width: 100%;
padding: 24rpx;
background: #f8f9fa;
padding: 24rpx 24rpx 24rpx 120rpx;
background: #ffffff;
border-radius: 12rpx;
font-size: 28rpx;
text-align: right;
color: #333;
min-height: 88rpx;
border: 1rpx solid #e9ecef;
......@@ -1729,22 +1802,11 @@ function testApiIntegration() {
.picker {
display: flex;
align-items: center;
justify-content: flex-end;
min-height: 88rpx;
}
.char-count {
position: absolute;
right: 20rpx;
top: 50%;
transform: translateY(-50%);
font-size: 24rpx;
color: #999;
pointer-events: none;
z-index: 1;
background: rgba(248, 249, 250, 0.8);
padding: 2rpx 8rpx;
border-radius: 4rpx;
}
}
.popup-buttons {
......@@ -1752,25 +1814,20 @@ function testApiIntegration() {
gap: 20rpx;
margin-top: 50rpx;
button {
flex: 1;
height: 88rpx;
border-radius: 12rpx;
font-size: 32rpx;
border: none;
font-weight: 600;
&.cancel-btn {
background: #f8f9fa;
color: #6c757d;
border: 1rpx solid #e9ecef;
}
.cancel-btn,
.confirm-btn {
width: 331rpx;
height: 94rpx;
flex: none;
}
&.confirm-btn {
background: #D4A574;
color: #fff;
.cancel-btn {
&:active {
opacity: 0.8;
}
}
.confirm-btn {
&:active {
opacity: 0.8;
}
......@@ -1792,32 +1849,32 @@ function testApiIntegration() {
@media screen and (max-width: 750rpx) {
.legend-section {
padding: 25rpx 30rpx;
.legend-item {
gap: 8rpx;
.legend-color {
width: 20rpx;
height: 20rpx;
}
.legend-text {
font-size: 24rpx;
}
}
}
.records-container {
.record-list {
padding: 0 20rpx 30rpx 20rpx;
.record-item {
.time-dot {
width: 120rpx;
margin-right: 15rpx;
}
.record-content {
padding: 24rpx;
}
......
......@@ -15,18 +15,18 @@
<!-- 喂养时间 -->
<view class="feeding-time">
<view class="baby-info" @click="showBabySwitch" v-if="babyList.length > 1">
<image class="avatar-img" :src="babyList[currentBabyIndex]?.avatar || feedingIndexRes.avatar">
<image class="avatar-img" :src="userStore.babyInfo?.babyAvatar || feedingIndexRes.avatar">
</image>
<view class="baby-name-section">
<text class="baby-name">{{ babyList[currentBabyIndex]?.name || '加载中...' }}</text>
<text class="baby-name">{{ userStore.babyInfo?.babyName || '加载中...' }}</text>
<image class="dropdown-icon" :src="feedingIndexRes.icon_arrow_yellow_drop" />
</view>
</view>
<view class="baby-info" v-else-if="babyList.length === 1">
<image class="avatar-img" :src="babyList[currentBabyIndex]?.avatar || feedingIndexRes.avatar">
<image class="avatar-img" :src="userStore.babyInfo?.babyAvatar || feedingIndexRes.avatar">
</image>
<view class="baby-name-section">
<text class="baby-name">{{ babyList[currentBabyIndex]?.name || '加载中...' }}</text>
<text class="baby-name">{{ userStore.babyInfo?.babyName || '加载中...' }}</text>
</view>
</view>
<view class="baby-info" v-else>
......@@ -405,10 +405,10 @@
<script setup>
import { ref, computed, onMounted, onUnmounted, getCurrentInstance } from 'vue'
import { onShow, onLoad } from '@dcloudio/uni-app'
import { onShow, onLoad, onHide } from '@dcloudio/uni-app'
import BabySwitchPopup from '@/components/BabySwitchPopup.vue'
import { feedingHome, feedingRecords, feedingFoodsCustom, feedingFoodsCustomAdd, feedingFoodsCustomDelete, feedingTimerStart, feedingTimerStop, feedingVoiceUpload, feedingVoiceResult } from '@/api/feeding.js'
import { useFeedStore } from '@/stores/feed.js'
import { useUserStore } from '@/stores/user.js'
import { jump, JumpType } from '../../utils'
import { getHealthField } from "@/api/common";
......@@ -517,6 +517,7 @@ const currentRecordId = ref(null) // 当前记录ID,用于区分新增和修
const isSubmitting = ref(false) // 提交状态
const bannerHandler = (item) => {
console.log(item);
jump({ type: item.JumpType, url: item.url })
}
const feedingTypes = ref([
......@@ -606,7 +607,8 @@ const voiceRecognitionState = ref({
const recorderManager = uni.getRecorderManager()
// 全局状态管理
const feedStore = useFeedStore()
const userStore = useUserStore()
const babyId = computed(() => userStore.babyInfo?.content?.id)
// 宝宝切换相关状态
const showBabySwitchPopup = ref(false)
......@@ -673,22 +675,25 @@ const isVoiceMode = computed(() => {
})
// 计算属性 - 获取宝宝信息
const babyList = computed(() => feedStore.babyList)
const currentBabyIndex = computed(() => feedStore.currentBabyIndex)
const currentBaby = computed(() => feedStore.getCurrentBaby())
const currentBabyId = computed(() => feedStore.getCurrentBabyId())
const babyList = computed(() => userStore.babyInfo?.allBabyBaseInfo || [])
const currentBabyIndex = computed(() => {
if (!babyList.value || !currentBaby.value) return 0
return babyList.value.findIndex(baby => baby.id === currentBaby.value.id)
})
const currentBaby = computed(() => userStore.babyInfo?.content)
const currentBabyId = computed(() => userStore.babyInfo?.content?.id)
// 页面加载时获取数据
onMounted(() => {
onMounted(async () => {
console.warn('页面加载,开始初始化数据...')
loadBabyInfo()
await loadBabyInfo()
loadFoodsData()
})
// 页面显示时刷新数据
onShow(() => {
// 刷新宝宝信息和首页数据
loadBabyInfo()
loadHomeData()
// 重置计时器状态,确保状态正确
resetTimerStatus()
......@@ -703,6 +708,20 @@ onShow(() => {
}
})
// 页面隐藏时同步计时器状态
onHide(() => {
// 如果页面隐藏时有计时器在运行,需要同步到后端
if (isLeftTimerRunning.value && leftTimerInterval) {
console.log('页面隐藏时同步左侧计时器状态')
// 这里可以选择是否调用后端接口同步状态
// 由于页面隐藏时通常不需要立即同步,可以等到页面显示时再同步
}
if (isRightTimerRunning.value && rightTimerInterval) {
console.log('页面隐藏时同步右侧计时器状态')
// 这里可以选择是否调用后端接口同步状态
}
})
// 页面卸载时清理计时器
onUnmounted(() => {
// 清理左侧计时器
......@@ -741,10 +760,7 @@ onLoad(async (options) => {
// 如果有其他参数,可以在这里处理
if (options.babyId) {
// 设置选中的宝宝
const babyIndex = feedStore.babyList.findIndex(baby => baby.id == options.babyId)
if (babyIndex > -1) {
feedStore.switchBaby(babyIndex)
}
await userStore.changeBabySelected(options.babyId)
}
if (options.feedingType) {
......@@ -808,7 +824,9 @@ async function loadBabyInfo() {
console.log('开始加载宝宝信息...')
// 使用全局状态管理加载宝宝信息
await feedStore.loadBabyInfo()
// 加载宝宝信息 - 由 userStore 管理
await userStore.loadBabyInfo()
console.log('宝宝信息加载完成:', userStore.babyInfo)
console.log('宝宝信息加载完成')
......@@ -830,7 +848,7 @@ async function loadBabyInfo() {
// 获取首页数据
async function loadHomeData() {
try {
const response = await feedingHome(feedStore.getCurrentBabyId())
const response = await feedingHome(babyId.value)
console.log('首页数据:', response)
if (response && response.data) {
......@@ -909,12 +927,13 @@ function initializePageData() {
timerData.value.leftDuration = Math.floor(data.leftTimerDuration / 1000) // 转换为秒
startLeftTimer()
} else {
// 如果接口显示没有左侧计时器在运行,但当前有计时器数据,则清空
if (timerData.value.leftDuration > 0) {
console.log('接口显示左侧计时器未运行,清空左侧计时器数据')
// 如果接口显示没有左侧计时器在运行,但当前有计时器数据,则清空并停止定时器
if (timerData.value.leftDuration > 0 || isLeftTimerRunning.value) {
console.log('接口显示左侧计时器未运行,清空左侧计时器数据并停止定时器')
timerData.value.leftDuration = 0
isLeftTimerRunning.value = false
stopLeftTimer()
}
isLeftTimerRunning.value = false
}
if (data.rightTimerRunning) {
......@@ -922,12 +941,13 @@ function initializePageData() {
timerData.value.rightDuration = Math.floor(data.rightTimerDuration / 1000) // 转换为秒
startRightTimer()
} else {
// 如果接口显示没有右侧计时器在运行,但当前有计时器数据,则清空
if (timerData.value.rightDuration > 0) {
console.log('接口显示右侧计时器未运行,清空右侧计时器数据')
// 如果接口显示没有右侧计时器在运行,但当前有计时器数据,则清空并停止定时器
if (timerData.value.rightDuration > 0 || isRightTimerRunning.value) {
console.log('接口显示右侧计时器未运行,清空右侧计时器数据并停止定时器')
timerData.value.rightDuration = 0
isRightTimerRunning.value = false
stopRightTimer()
}
isRightTimerRunning.value = false
}
// 如果有计时器在运行,切换到计时器模式
......@@ -1225,7 +1245,7 @@ function toggleRecording() {
}
async function toggleTimer(side) {
const babyId = feedStore.getCurrentBabyId()
const currentBabyId = babyId.value
if (side === 'left') {
// 检查是否已达到上限
......@@ -1242,7 +1262,7 @@ async function toggleTimer(side) {
// 开始左侧计时
try {
const response = await feedingTimerStart({
babyId: babyId,
babyId: currentBabyId,
side: 'left'
})
console.log('开始左侧计时成功:', response)
......@@ -1259,7 +1279,7 @@ async function toggleTimer(side) {
// 停止左侧计时
try {
const response = await feedingTimerStop({
babyId: babyId,
babyId: currentBabyId,
side: 'left'
})
console.log('停止左侧计时成功:', response)
......@@ -1288,7 +1308,7 @@ async function toggleTimer(side) {
// 开始右侧计时
try {
const response = await feedingTimerStart({
babyId: babyId,
babyId: currentBabyId,
side: 'right'
})
console.log('开始右侧计时成功:', response)
......@@ -1305,7 +1325,7 @@ async function toggleTimer(side) {
// 停止右侧计时
try {
const response = await feedingTimerStop({
babyId: babyId,
babyId: currentBabyId,
side: 'right'
})
console.log('停止右侧计时成功:', response)
......@@ -1384,8 +1404,8 @@ function stopRightTimer() {
// 自动停止左侧计时器(调用后端接口)
async function autoStopLeftTimer() {
const babyId = feedStore.getCurrentBabyId()
if (!babyId) {
const currentBabyId = babyId.value
if (!currentBabyId) {
console.warn('没有选择宝宝,无法停止计时器')
return
}
......@@ -1393,7 +1413,7 @@ async function autoStopLeftTimer() {
try {
console.log('自动停止左侧计时器')
const response = await feedingTimerStop({
babyId: babyId,
babyId: currentBabyId,
side: 'left'
})
console.log('自动停止左侧计时器成功:', response)
......@@ -1405,8 +1425,8 @@ async function autoStopLeftTimer() {
// 自动停止右侧计时器(调用后端接口)
async function autoStopRightTimer() {
const babyId = feedStore.getCurrentBabyId()
if (!babyId) {
const currentBabyId = babyId.value
if (!currentBabyId) {
console.warn('没有选择宝宝,无法停止计时器')
return
}
......@@ -1414,7 +1434,7 @@ async function autoStopRightTimer() {
try {
console.log('自动停止右侧计时器')
const response = await feedingTimerStop({
babyId: babyId,
babyId: currentBabyId,
side: 'right'
})
console.log('自动停止右侧计时器成功:', response)
......@@ -1426,8 +1446,8 @@ async function autoStopRightTimer() {
// 停止所有计时器
async function stopAllTimers() {
const currentBaby = feedStore.getCurrentBaby()
if (!currentBaby || !currentBaby.id) {
const currentBabyId = babyId.value
if (!currentBabyId) {
console.warn('没有选择宝宝,无法停止计时器')
return
}
......@@ -1437,7 +1457,7 @@ async function stopAllTimers() {
if (isLeftTimerRunning.value) {
console.log('保存记录前停止左侧计时器')
const leftResponse = await feedingTimerStop({
babyId: currentBaby.id,
babyId: currentBabyId,
side: 'left'
})
console.log('停止左侧计时器成功:', leftResponse)
......@@ -1449,7 +1469,7 @@ async function stopAllTimers() {
if (isRightTimerRunning.value) {
console.log('保存记录前停止右侧计时器')
const rightResponse = await feedingTimerStop({
babyId: currentBaby.id,
babyId: currentBabyId,
side: 'right'
})
console.log('停止右侧计时器成功:', rightResponse)
......@@ -1546,7 +1566,7 @@ async function completeRecord() {
// 验证记录数据
function validateRecordData() {
const currentBaby = feedStore.getCurrentBaby()
const currentBaby = userStore.babyInfo?.content
// 验证宝宝信息
if (!currentBaby || !currentBaby.id) {
......@@ -1617,7 +1637,7 @@ function validateRecordData() {
// 构建记录数据
function buildRecordData() {
const currentBaby = feedStore.getCurrentBaby()
const currentBaby = userStore.babyInfo?.content
const recordTime = formatCurrentTime()
// 基础数据
......@@ -2777,9 +2797,10 @@ function showBabySwitch() {
}
}
function onBabyChange(baby, index) {
feedStore.switchBaby(index)
console.log('切换到宝宝:', baby.name, '索引:', index)
async function onBabyChange(baby, index) {
// 切换宝宝
await userStore.changeBabySelected(baby.id)
console.log('切换到宝宝:', baby.babyName, '索引:', index)
// 切换宝宝后重新加载该宝宝的喂养数据
loadHomeData()
......
......@@ -8,7 +8,7 @@
<view class="nav-left">
<image :src="feedingRecordRes.icon_return" class="back-btn" @click="goBack" />
<image :src="feedingRecordRes.icon_star" class="baby-icon-star" />
<view class="baby-info" @click="showBabySwitch" v-if="babyList.length > 1">
<view class="baby-info" @click="showBabySwitch" v-if="hasMultipleStage2Babies">
<text class="baby-name">{{ getCurrentBabyName() }}</text>
<text class="baby-age">{{ getCurrentBabyAge() }}</text>
</view>
......@@ -152,29 +152,28 @@
<!-- 编辑弹窗 -->
<view class="popup-mask" v-if="showEditPopup" @click="closeEditPopup" @touchmove.prevent>
<view class="popup-content" @click.stop @touchmove.stop>
<view class="popup-title">修改喂养记录</view>
<view class="popup-title">确认修改内容</view>
<view class="form-item">
<text class="label">时间:</text>
<text class="label">喂养时间</text>
<picker mode="time" :value="editForm.time" @change="onEditTimeChange">
<view class="picker">{{ editForm.time || '请选择时间' }}</view>
</picker>
</view>
<view class="form-item">
<text class="label">类型:</text>
<text class="label">喂养方式</text>
<picker :range="feedingTypes" @change="onEditTypeChange">
<view class="picker">{{ editForm.type || '请选择类型' }}</view>
</picker>
</view>
<view class="form-item">
<text class="label">喂养详情:</text>
<view class="input-container">
<input class="input" v-model="editForm.content" placeholder="请输入具体内容" maxlength="20" />
<text class="char-count">{{ editForm.content.length }}/20</text>
</view>
<text class="label">喂养详情</text>
<view class="input-container">
<input class="input" v-model="editForm.content" :placeholder="getEditFormPlaceholder()" maxlength="20" />
</view>
</view>
<view class="popup-buttons">
<button class="cancel-btn" @click="closeEditPopup">取消</button>
<button class="confirm-btn" @click="saveEditRecord">保存修改</button>
<image :src="feedingRecordRes.icon_change_btn_cancel" class="cancel-btn" @click="closeEditPopup" />
<image :src="feedingRecordRes.icon_change_btn_confirm" class="confirm-btn" @click="saveEditRecord" />
</view>
</view>
</view>
......@@ -195,7 +194,7 @@ import { ref, computed, onMounted, onUnmounted, watch, nextTick,getCurrentInstan
import { onLoad, onShow } from '@dcloudio/uni-app'
import BabySwitchPopup from '@/components/BabySwitchPopup.vue'
import { feedingRecordsByDate, feedingRecordsCalendarStatus, feedingRecords as feedingRecordsAPI } from '@/api/feeding.js'
import { useFeedStore } from '@/stores/feed.js'
import { useUserStore } from '@/stores/user.js'
// API 集成说明:
// 1. 使用 /c/feeding/records GET 方法查询指定日期的喂养记录列表
......@@ -230,6 +229,9 @@ const feedingRecordRes = {
icon_return: $baseUrl + `feedingRecord/${version}/icon_return.png`,
icon_baby_change: $baseUrl + `feedingRecord/${version}/icon_baby_change.png`,
add_btn: $baseUrl + `feedingRecord/${version}/addBtn.png`,
icon_change_btn_confirm: $baseUrl + `feedingRecord/${version}/icon_change_btn_confirm.png`,
icon_change_btn_cancel: $baseUrl + `feedingRecord/${version}/icon_change_btn_cancel.png`,
}
......@@ -246,7 +248,8 @@ const forceUpdate = ref(0)
const currentMonthKey = ref('')
// 全局状态管理
const feedStore = useFeedStore()
const userStore = useUserStore()
const babyId = computed(() => userStore.babyInfo?.content?.id)
// 宝宝切换相关状态
const showBabySwitchPopup = ref(false)
......@@ -288,10 +291,20 @@ const recordsCache = ref(new Map()) // 记录数据缓存,避免重复请求
const calendarCache = ref(new Map()) // 日历状态缓存,避免重复请求
// 计算属性 - 获取宝宝信息
const babyList = computed(() => feedStore.babyList)
const currentBabyIndex = computed(() => feedStore.currentBabyIndex)
const currentBaby = computed(() => feedStore.getCurrentBaby())
const currentBabyId = computed(() => feedStore.getCurrentBabyId())
const babyList = computed(() => userStore.babyInfo?.allBabyBaseInfo || [])
const currentBabyIndex = computed(() => {
if (!babyList.value || !currentBaby.value) return 0
return babyList.value.findIndex(baby => baby.id === currentBaby.value.id)
})
const currentBaby = computed(() => userStore.babyInfo?.content)
const currentBabyId = computed(() => userStore.babyInfo?.content?.id)
// 检查是否有多个 stage == 2 的宝宝
const hasMultipleStage2Babies = computed(() => {
if (!babyList.value || babyList.value.length === 0) return false
const stage2Babies = babyList.value.filter(baby => baby.babyStage === 2)
return stage2Babies.length > 1
})
// 计算属性 - 当前选中日期的记录
const todayRecords = computed(() => {
......@@ -606,10 +619,32 @@ function editRecord(index) {
console.log('record.foodDetails:', record.foodDetails)
console.log('record.content:', record.content)
// 根据记录类型设置不同的字段
let content = ''
if (record.type === '母乳亲喂') {
// 母乳亲喂:优先显示 foodDetails,如果没有则从左右时间构建
if (record.foodDetails) {
content = record.foodDetails
} else {
const leftTime = record.leftDuration || ''
const rightTime = record.rightDuration || ''
content = `${leftTime} ${rightTime}`.trim()
}
} else if (record.type === '母乳瓶喂') {
// 母乳瓶喂:优先显示 foodDetails,如果没有则显示 amount
content = record.foodDetails || record.amount || ''
} else if (record.type === '奶粉喂养') {
// 奶粉喂养:优先显示 foodDetails,如果没有则显示 amount
content = record.foodDetails || record.amount || ''
} else if (record.type === '辅食') {
// 辅食:显示食物详情
content = record.foodDetails || record.content || ''
}
editForm.value = {
time: record.time || getCurrentTime(), // 使用记录的原始时间,如果没有则使用当前时间
type: record.type || '',
content: record.foodDetails || record.content || '' // 优先使用foodDetails
content: content
}
console.log('设置后的editForm:', editForm.value)
......@@ -652,12 +687,37 @@ async function saveEditRecord() {
})
const { index, record } = editingRecord.value
const apiData = {
// 根据记录类型处理不同的数据
let apiData = {
recordId: record.recordId,
babyId: feedStore.getCurrentBabyId(),
babyId: babyId.value,
recordTime: formatDateTimeString(currentSelectedDate.value, editForm.value.time),
feedingType: getFeedingTypeId(editForm.value.type),
foodDetails: editForm.value.content // 统一使用foodDetails字段
feedingType: getFeedingTypeId(editForm.value.type)
}
// 所有类型都使用 foodDetails 字段保存
apiData.foodDetails = editForm.value.content || ''
// 根据记录类型设置其他字段
if (editForm.value.type === '母乳亲喂') {
// 母乳亲喂:解析时间(格式:时间1 时间2)
const content = editForm.value.content || ''
const timeParts = content.trim().split(/\s+/)
if (timeParts.length >= 1 && timeParts[0]) {
apiData.durationLeftSeconds = parseTimeToSeconds(timeParts[0])
}
if (timeParts.length >= 2 && timeParts[1]) {
apiData.durationRightSeconds = parseTimeToSeconds(timeParts[1])
}
} else if (editForm.value.type === '母乳瓶喂' || editForm.value.type === '奶粉喂养') {
// 母乳瓶喂和奶粉喂养:解析奶量
const content = editForm.value.content || ''
const volumeMatch = content.match(/(\d+)ml/)
if (volumeMatch) {
apiData.volume = parseInt(volumeMatch[1])
}
}
const response = await feedingRecordsAPI(apiData)
......@@ -714,9 +774,10 @@ function showBabySwitch() {
}
}
function onBabyChange(baby, index) {
feedStore.switchBaby(index)
console.log('切换到宝宝:', baby.name, '索引:', index)
async function onBabyChange(baby, index) {
// 切换宝宝
await userStore.changeBabySelected(baby.id)
console.log('切换到宝宝:', baby.babyName, '索引:', index)
// 切换宝宝后清空缓存,重新加载数据
clearCache()
......@@ -774,9 +835,8 @@ function calculateBabyAge(birthday) {
// 安全获取当前宝宝姓名
function getCurrentBabyName() {
try {
const currentBaby = babyList.value[currentBabyIndex.value]
if (currentBaby && currentBaby.name) {
return currentBaby.name
if (userStore.babyInfo && userStore.babyInfo.babyName) {
return userStore.babyInfo.babyName
}
return '宝宝'
} catch (error) {
......@@ -788,9 +848,8 @@ function getCurrentBabyName() {
// 安全获取当前宝宝年龄
function getCurrentBabyAge() {
try {
const currentBaby = babyList.value[currentBabyIndex.value]
if (currentBaby && currentBaby.birthday) {
return calculateBabyAge(currentBaby.birthday)
if (userStore.babyInfo && userStore.babyInfo.babyAge) {
return userStore.babyInfo.babyAge
}
return '0天'
} catch (error) {
......@@ -808,7 +867,7 @@ async function loadRecordsByDate(date) {
}
// 检查缓存
const cacheKey = `${date}_${feedStore.getCurrentBabyId()}`
const cacheKey = `${date}_${babyId.value}`
const cachedData = recordsCache.value.get(cacheKey)
if (cachedData && Date.now() - cachedData.timestamp < 5 * 60 * 1000) { // 5分钟缓存
console.log('使用缓存的记录数据:', date)
......@@ -823,7 +882,7 @@ async function loadRecordsByDate(date) {
if (loadingRecords.value.size === 1) {
isLoading.value = true
}
const babyId = feedStore.getCurrentBabyId()
const currentBabyId = babyId.value
// 添加超时处理
const timeoutPromise = new Promise((_, reject) => {
......@@ -831,7 +890,7 @@ async function loadRecordsByDate(date) {
})
const apiPromise = feedingRecordsByDate({
babyId: babyId,
babyId: currentBabyId,
date: date
})
......@@ -957,7 +1016,7 @@ async function loadCalendarStatus(month) {
try {
const startTime = Date.now()
loadingCalendar.value.add(month)
const babyId = feedStore.getCurrentBabyId()
const currentBabyId = babyId.value
// 添加超时处理
const timeoutPromise = new Promise((_, reject) => {
......@@ -965,7 +1024,7 @@ async function loadCalendarStatus(month) {
})
const apiPromise = feedingRecordsCalendarStatus({
babyId: babyId,
babyId: currentBabyId,
month: month // 格式:YYYY-MM
})
......@@ -1118,6 +1177,25 @@ function formatDuration(seconds) {
}
}
// 解析时间格式为秒数
function parseTimeToSeconds(timeString) {
if (!timeString) return 0
const parts = timeString.split(':')
if (parts.length === 2) {
const minutes = parseInt(parts[0], 10)
const seconds = parseInt(parts[1], 10)
return minutes * 60 + seconds
}
return 0
}
// 获取编辑表单的占位符
function getEditFormPlaceholder() {
return '输入具体内容'
}
function getFeedingTypeLabel(type) {
const typeMap = {
1: '母乳亲喂',
......@@ -1302,8 +1380,11 @@ watch(currentDate, (newDate, oldDate) => {
}
}, { immediate: false })
onMounted(() => {
onMounted(async () => {
// 组件挂载后的操作
// 加载宝宝信息
await userStore.loadBabyInfo()
console.log('宝宝信息加载完成:', userStore.babyInfo)
})
// 页面卸载时清理资源
......@@ -1316,7 +1397,11 @@ onUnmounted(() => {
})
// 页面显示时刷新数据
onShow(() => {
onShow(async () => {
// 加载宝宝信息
await userStore.loadBabyInfo()
console.log('宝宝信息加载完成:', userStore.babyInfo)
// 如果已经有选中日期,刷新当前日期的记录
if (currentSelectedDate.value) {
loadRecordsByDate(currentSelectedDate.value)
......@@ -1920,7 +2005,7 @@ function testApiIntegration() {
}
.popup-content {
background: #fff;
background: #f6f8fa;
width: 100%;
border-radius: 20rpx 20rpx 0 0;
padding: 40rpx 30rpx;
......@@ -1932,18 +2017,23 @@ function testApiIntegration() {
font-size: 36rpx;
font-weight: 600;
color: #333;
text-align: center;
text-align: left;
margin-bottom: 40rpx;
}
.form-item {
margin-bottom: 30rpx;
position: relative;
.label {
position: absolute;
left: 24rpx;
top: 50%;
transform: translateY(-50%);
font-size: 28rpx;
color: #333;
margin-bottom: 12rpx;
display: block;
z-index: 2;
pointer-events: none;
}
.input-container {
......@@ -1954,10 +2044,11 @@ function testApiIntegration() {
.picker,
.input {
width: 100%;
padding: 24rpx;
background: #f8f9fa;
padding: 24rpx 24rpx 24rpx 120rpx;
background: #ffffff;
border-radius: 12rpx;
font-size: 28rpx;
text-align: right;
min-height: 88rpx;
color: #333;
......@@ -1965,20 +2056,15 @@ function testApiIntegration() {
box-sizing: border-box;
}
.char-count {
position: absolute;
right: 20rpx;
top: 50%;
transform: translateY(-50%);
font-size: 24rpx;
color: #999;
pointer-events: none;
z-index: 1;
background: rgba(248, 249, 250, 0.8);
padding: 2rpx 8rpx;
border-radius: 4rpx;
.picker {
display: flex;
align-items: center;
justify-content: flex-end;
min-height: 88rpx;
}
.picker {
display: flex;
align-items: center;
......@@ -1991,25 +2077,20 @@ function testApiIntegration() {
gap: 20rpx;
margin-top: 50rpx;
button {
flex: 1;
height: 88rpx;
border-radius: 50rpx;
font-size: 32rpx;
border: none;
font-weight: 600;
&.cancel-btn {
background: #f8f9fa;
color: #6c757d;
border: 1rpx solid #e9ecef;
}
.cancel-btn,
.confirm-btn {
width: 331rpx;
height: 94rpx;
flex: none;
}
&.confirm-btn {
background: #D4A574;
color: #fff;
.cancel-btn {
&:active {
opacity: 0.8;
}
}
.confirm-btn {
&:active {
opacity: 0.8;
}
......
......@@ -26,12 +26,13 @@ export const useFeedStore = defineStore("feed", {
* 处理宝宝列表数据
*/
processBabyList(data) {
if (data.allBabyBaseInfo && Array.isArray(data.allBabyBaseInfo)) {
// 转换接口数据格式为组件需要的格式
this.babyList = data.allBabyBaseInfo.map(baby => ({
id: baby.id,
name: baby.babyName || baby.content?.babyName || '未命名',
avatar: baby.content?.babyAvatar || '/static/feedingIndex/v1/avatar.png',
avatar: baby.content?.babyAvatar ,
gender: baby.content?.babyGender,
birthday: baby.content?.babyBirthday,
babyStage: baby.babyStage,
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment