Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
飞
飞鹤小程序
Project
Project
Details
Activity
Releases
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Commits
Issue Boards
Open sidebar
FH
飞鹤小程序
Commits
40699575
Commit
40699575
authored
Sep 02, 2025
by
张九刚
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
feat: backup
parent
2f99e2c5
Changes
5
Show whitespace changes
Inline
Side-by-side
Showing
5 changed files
with
4193 additions
and
4019 deletions
+4193
-4019
popup-tip.vue
components/popup-tip/popup-tip.vue
+8
-1
feedingIndex.vue
pages/feedingIndex/feedingIndex.vue
+4143
-4008
postnatalCheckUp.vue
pages/postnatalCheckUp/postnatalCheckUp.vue
+24
-3
shengzhangTestResult.vue
pages/shengzhangTestResult/shengzhangTestResult.vue
+16
-6
shengzhangTools.vue
pages/shengzhangTools/shengzhangTools.vue
+2
-1
No files found.
components/popup-tip/popup-tip.vue
View file @
40699575
...
...
@@ -161,7 +161,14 @@ const onAdd = () => {
modifyState
()
break
;
case
'3'
:
if
(
getCurrentPages
().
length
>
1
)
{
uni
.
navigateBack
()
}
else
{
uni
.
reLaunch
({
url
:
'/pages/index/index'
})
}
break
;
default
:
break
;
...
...
pages/feedingIndex/feedingIndex.vue
View file @
40699575
...
...
@@ -417,33 +417,68 @@
</view>
</uni-popup>
<popupTip
v-if=
"isTip"
type=
"1"
@
statusChange=
"onPopupTipBabyChange"
@
close=
"isTip = false"
></popupTip>
<popupTip
v-if=
"isTip"
type=
"1"
@
statusChange=
"onPopupTipBabyChange"
@
afterPhone=
"isShowRegisterLayer = true"
:isNotLogin=
"isNotLogin"
@
close=
"isTip = false"
></popupTip>
<RegisterLayer
v-model=
"isShowRegisterLayer"
@
confirm=
"onRegisterConfirm"
/>
</
template
>
<
script
setup
>
import
{
ref
,
computed
,
onMounted
,
onUnmounted
,
getCurrentInstance
}
from
'vue'
import
{
onShow
,
onLoad
,
onHide
,
onShareAppMessage
,
onShareTimeline
}
from
'@dcloudio/uni-app'
import
BabySwitchPopup
from
'@/components/BabySwitchPopup.vue'
import
popupTip
from
'../../components/popup-tip/popup-tip.vue'
import
{
fetchFeedingJSON
,
feedingHome
,
feedingRecords
,
feedingFoodsCustom
,
feedingFoodsCustomAdd
,
feedingFoodsCustomDelete
,
feedingTimerStart
,
feedingTimerStop
,
feedingVoiceUpload
,
feedingVoiceResult
}
from
'@/api/feeding.js'
import
{
useUserStore
}
from
'@/stores/user.js'
import
{
jump
,
JumpType
,
showLoading
}
from
'../../utils'
import
{
getHealthField
}
from
"@/api/common"
;
import
md
from
'../../md'
// 弹窗引用
const
addFoodPopup
=
ref
(
null
)
const
successPopup
=
ref
(
null
)
const
{
proxy
}
=
getCurrentInstance
();
const
$baseUrl
=
proxy
.
$baseUrl
;
const
version
=
'v1'
// 计时器上限时间(秒)
const
TIMER_MAX_DURATION
=
3600
const
feedingIndexRes
=
{
import
{
ref
,
computed
,
onMounted
,
onUnmounted
,
getCurrentInstance
}
from
'vue'
import
{
onShow
,
onLoad
,
onHide
,
onShareAppMessage
,
onShareTimeline
}
from
'@dcloudio/uni-app'
import
BabySwitchPopup
from
'@/components/BabySwitchPopup.vue'
import
RegisterLayer
from
'@/components/RegisterLayer.vue'
import
popupTip
from
'../../components/popup-tip/popup-tip.vue'
import
{
fetchFeedingJSON
,
feedingHome
,
feedingRecords
,
feedingFoodsCustom
,
feedingFoodsCustomAdd
,
feedingFoodsCustomDelete
,
feedingTimerStart
,
feedingTimerStop
,
feedingVoiceUpload
,
feedingVoiceResult
}
from
'@/api/feeding.js'
import
{
useUserStore
}
from
'@/stores/user.js'
import
{
jump
,
JumpType
,
showLoading
}
from
'../../utils'
import
{
getHealthField
}
from
"@/api/common"
;
import
md
from
'../../md'
// 弹窗引用
const
addFoodPopup
=
ref
(
null
)
const
successPopup
=
ref
(
null
)
const
{
proxy
}
=
getCurrentInstance
();
const
$baseUrl
=
proxy
.
$baseUrl
;
const
version
=
'v1'
// 计时器上限时间(秒)
const
TIMER_MAX_DURATION
=
3600
const
feedingIndexRes
=
{
// 轮播图
banner
:
$baseUrl
+
`feedingIndex/
${
version
}
/banner.png`
,
...
...
@@ -512,26 +547,26 @@ const feedingIndexRes = {
// 识别成功弹窗
icon_btn_confirm
:
$baseUrl
+
`feedingIndex/
${
version
}
/icon_btn_confirm.png`
,
icon_btn_cancel
:
$baseUrl
+
`feedingIndex/
${
version
}
/icon_btn_cancel.png`
,
}
}
const
swiperData
=
ref
([
const
swiperData
=
ref
([
]);
const
indicatorStyle
=
`height: 40px; border: none;`
]);
const
indicatorStyle
=
`height: 40px; border: none;`
// 当前时间,使用 home 接口的 timestamp
const
currentTime
=
ref
(
null
)
// 当前时间,使用 home 接口的 timestamp
const
currentTime
=
ref
(
null
)
// 日期范围限制
const
earliestDateString
=
ref
(
'2020-01-01'
)
const
latestDateString
=
ref
(
'2030-12-31'
)
// 日期范围限制
const
earliestDateString
=
ref
(
'2020-01-01'
)
const
latestDateString
=
ref
(
'2030-12-31'
)
// 时间选择器引用
const
timePickerRef
=
ref
(
null
)
const
voiceTimePickerRef
=
ref
(
null
)
// 时间选择器引用
const
timePickerRef
=
ref
(
null
)
const
voiceTimePickerRef
=
ref
(
null
)
// 接口返回的数据
const
homeData
=
ref
({
// 接口返回的数据
const
homeData
=
ref
({
timestamp
:
null
,
lastRecordType
:
0
,
lastBreastMilkVolume
:
0
,
...
...
@@ -540,12 +575,12 @@ const homeData = ref({
leftTimerDuration
:
0
,
rightTimerRunning
:
false
,
rightTimerDuration
:
0
})
})
// 记录相关数据
const
currentRecordId
=
ref
(
null
)
// 当前记录ID,用于区分新增和修改
const
isSubmitting
=
ref
(
false
)
// 提交状态
const
bannerHandler
=
(
item
)
=>
{
// 记录相关数据
const
currentRecordId
=
ref
(
null
)
// 当前记录ID,用于区分新增和修改
const
isSubmitting
=
ref
(
false
)
// 提交状态
const
bannerHandler
=
(
item
)
=>
{
// 检查是否正在录音
if
(
recordingState
.
value
.
isRecording
||
voiceRecognitionState
.
value
.
isRecording
)
{
uni
.
showToast
({
...
...
@@ -562,41 +597,60 @@ const bannerHandler = (item) => {
});
console
.
log
(
item
);
jump
({
type
:
item
.
jumpType
,
url
:
item
.
url
,
extra
:
item
.
extra
})
}
jump
({
type
:
item
.
jumpType
,
url
:
item
.
url
,
extra
:
item
.
extra
})
}
const
showTimePicker
=
()
=>
{
const
showTimePicker
=
()
=>
{
md
.
sensorLogTake
({
xcxClick
:
"小程序页面点击事件"
,
pageName
:
"喂养工具首页"
,
buttonName
:
"选择喂养时间"
,
});
}
}
const
feedingTypes
=
ref
([
{
value
:
'breastfeeding'
,
label
:
'母乳亲喂'
,
icon
:
feedingIndexRes
.
icon_muruqinwei
},
{
value
:
'bottle'
,
label
:
'母乳瓶喂'
,
icon
:
feedingIndexRes
.
icon_murupinwei
},
{
value
:
'formula'
,
label
:
'奶粉喂养'
,
icon
:
feedingIndexRes
.
icon_naifen
},
{
value
:
'food'
,
label
:
'辅食'
,
icon
:
feedingIndexRes
.
icon_fushi
}
])
const
feedingTypes
=
ref
([{
value
:
'breastfeeding'
,
label
:
'母乳亲喂'
,
icon
:
feedingIndexRes
.
icon_muruqinwei
},
{
value
:
'bottle'
,
label
:
'母乳瓶喂'
,
icon
:
feedingIndexRes
.
icon_murupinwei
},
{
value
:
'formula'
,
label
:
'奶粉喂养'
,
icon
:
feedingIndexRes
.
icon_naifen
},
{
value
:
'food'
,
label
:
'辅食'
,
icon
:
feedingIndexRes
.
icon_fushi
}
])
// 根据接口数据初始化选中的喂养类型
const
selectedType
=
ref
(
'breastfeeding'
)
// 根据接口数据初始化选中的喂养类型
const
selectedType
=
ref
(
'breastfeeding'
)
// 为每种喂养方式设置独立的记录方法
const
recordMethods
=
ref
({
// 为每种喂养方式设置独立的记录方法
const
recordMethods
=
ref
({
breastfeeding
:
'manual'
,
bottle
:
'manual'
,
formula
:
'manual'
,
food
:
'manual'
})
const
isRecording
=
ref
(
false
)
const
isLeftTimerRunning
=
ref
(
false
)
const
isRightTimerRunning
=
ref
(
false
)
})
const
isRecording
=
ref
(
false
)
const
isLeftTimerRunning
=
ref
(
false
)
const
isRightTimerRunning
=
ref
(
false
)
// 辅食数据结构 - 使用接口数据
const
foodCategories
=
ref
({
// 辅食数据结构 - 使用接口数据
const
foodCategories
=
ref
({
主食
:
{
items
:
[],
customItems
:
[],
...
...
@@ -617,21 +671,21 @@ const foodCategories = ref({
customItems
:
[],
expanded
:
false
}
})
})
// 辅食ID映射,用于删除操作
const
foodIdMap
=
ref
(
new
Map
())
// 辅食ID映射,用于删除操作
const
foodIdMap
=
ref
(
new
Map
())
// 辅食类型映射
const
foodTypeMap
=
{
// 辅食类型映射
const
foodTypeMap
=
{
1
:
'主食'
,
2
:
'蔬菜'
,
3
:
'水果'
,
4
:
'其他'
}
}
// 辅食选择状态
const
foodSelectionState
=
ref
({
// 辅食选择状态
const
foodSelectionState
=
ref
({
isEditMode
:
false
,
// 是否处于编辑模式
showAddPopup
:
false
,
// 是否显示添加弹窗
currentCategory
:
''
,
// 当前添加的分类
...
...
@@ -640,12 +694,12 @@ const foodSelectionState = ref({
originalFoodData
:
null
,
// 保存原始辅食数据,用于恢复
isAddingFood
:
false
,
// 添加辅食防连点状态
isDeletingFood
:
false
// 删除辅食防连点状态
})
})
// 记录成功弹窗状态 - 已移除,改用 .open() 和 .close() 方法
// 记录成功弹窗状态 - 已移除,改用 .open() 和 .close() 方法
// 语音识别状态
const
voiceRecognitionState
=
ref
({
// 语音识别状态
const
voiceRecognitionState
=
ref
({
isRecording
:
false
,
// 是否正在录音
showResultPage
:
false
,
// 是否显示识别结果页面
recognizedText
:
''
,
// 识别结果文本
...
...
@@ -660,22 +714,23 @@ const voiceRecognitionState = ref({
recordDate
:
''
,
// 记录日期
recordTime
:
''
,
// 记录时间
voiceDateTime
:
''
// 完整的日期时间字符串
})
// 录音管理器
const
recorderManager
=
uni
.
getRecorderManager
()
})
// 全局状态管理
const
userStore
=
useUserStore
()
const
babyId
=
computed
(()
=>
userStore
.
babyInfo
?.
content
?.
id
)
// 录音管理器
const
recorderManager
=
uni
.
getRecorderManager
()
// 宝宝切换相关状态
const
showBabySwitchPopup
=
ref
(
false
)
// 全局状态管理
const
userStore
=
useUserStore
()
const
babyId
=
computed
(()
=>
userStore
.
babyInfo
?.
content
?.
id
)
const
isTip
=
ref
(
true
)
// 宝宝切换相关状态
const
showBabySwitchPopup
=
ref
(
false
)
// 为每种喂养方式设置独立的数据 - 根据接口数据初始化
const
feedingData
=
ref
({
const
isTip
=
ref
(
true
)
const
isNotLogin
=
ref
(
false
)
const
isShowRegisterLayer
=
ref
(
false
)
// 为每种喂养方式设置独立的数据 - 根据接口数据初始化
const
feedingData
=
ref
({
breastfeeding
:
{
leftDuration
:
5
,
rightDuration
:
5
...
...
@@ -689,37 +744,42 @@ const feedingData = ref({
food
:
{
selectedItems
:
[]
}
})
})
// 刻度标记数组 (0-500ml,每5ml一个刻度)
const
scaleMarks
=
ref
([
0
,
50
,
100
,
150
,
200
,
250
,
300
,
350
,
400
,
450
,
500
])
// 刻度标记数组 (0-500ml,每5ml一个刻度)
const
scaleMarks
=
ref
([
0
,
50
,
100
,
150
,
200
,
250
,
300
,
350
,
400
,
450
,
500
])
// picker-view相关数据
const
pickerAmounts
=
ref
([
0
,
5
,
10
,
15
,
20
,
25
,
30
,
35
,
40
,
45
,
50
,
55
,
60
,
65
,
70
,
75
,
80
,
85
,
90
,
95
,
100
,
105
,
110
,
115
,
120
,
125
,
130
,
135
,
140
,
145
,
150
,
155
,
160
,
165
,
170
,
175
,
180
,
185
,
190
,
195
,
200
,
205
,
210
,
215
,
220
,
225
,
230
,
235
,
240
,
245
,
250
,
255
,
260
,
265
,
270
,
275
,
280
,
285
,
290
,
295
,
300
,
305
,
310
,
315
,
320
,
325
,
330
,
335
,
340
,
345
,
350
,
355
,
360
,
365
,
370
,
375
,
380
,
385
,
390
,
395
,
400
,
405
,
410
,
415
,
420
,
425
,
430
,
435
,
440
,
445
,
450
,
455
,
460
,
465
,
470
,
475
,
480
,
485
,
490
,
495
,
500
])
// picker-view相关数据
const
pickerAmounts
=
ref
([
0
,
5
,
10
,
15
,
20
,
25
,
30
,
35
,
40
,
45
,
50
,
55
,
60
,
65
,
70
,
75
,
80
,
85
,
90
,
95
,
100
,
105
,
110
,
115
,
120
,
125
,
130
,
135
,
140
,
145
,
150
,
155
,
160
,
165
,
170
,
175
,
180
,
185
,
190
,
195
,
200
,
205
,
210
,
215
,
220
,
225
,
230
,
235
,
240
,
245
,
250
,
255
,
260
,
265
,
270
,
275
,
280
,
285
,
290
,
295
,
300
,
305
,
310
,
315
,
320
,
325
,
330
,
335
,
340
,
345
,
350
,
355
,
360
,
365
,
370
,
375
,
380
,
385
,
390
,
395
,
400
,
405
,
410
,
415
,
420
,
425
,
430
,
435
,
440
,
445
,
450
,
455
,
460
,
465
,
470
,
475
,
480
,
485
,
490
,
495
,
500
])
// 滑动相关状态
const
isDragging
=
ref
(
false
)
const
startY
=
ref
(
0
)
const
startAmount
=
ref
(
0
)
// 滑动相关状态
const
isDragging
=
ref
(
false
)
const
startY
=
ref
(
0
)
const
startAmount
=
ref
(
0
)
// 计时器数据 - 根据接口数据初始化
const
timerData
=
ref
({
// 计时器数据 - 根据接口数据初始化
const
timerData
=
ref
({
leftDuration
:
0
,
rightDuration
:
0
})
})
// 计时器间隔ID
let
leftTimerInterval
=
null
let
rightTimerInterval
=
null
// 计时器间隔ID
let
leftTimerInterval
=
null
let
rightTimerInterval
=
null
// 计算属性 - 判断是否显示表单
const
shouldShowForm
=
computed
(()
=>
{
// 计算属性 - 判断是否显示表单
const
shouldShowForm
=
computed
(()
=>
{
const
currentMethod
=
recordMethods
.
value
[
selectedType
.
value
]
return
currentMethod
===
'manual'
// 只有手动模式显示表单
})
})
// 计算属性 - 同步picker-view的值
const
pickerValue
=
computed
({
// 计算属性 - 同步picker-view的值
const
pickerValue
=
computed
({
get
()
{
const
currentAmount
=
feedingData
.
value
[
selectedType
.
value
].
amount
const
index
=
pickerAmounts
.
value
.
indexOf
(
currentAmount
)
...
...
@@ -728,28 +788,28 @@ const pickerValue = computed({
set
(
value
)
{
// 这个setter不会被直接调用,但需要保持响应式
}
})
})
// 计算属性 - 判断是否为语音模式(辅食除外)
const
isVoiceMode
=
computed
(()
=>
{
// 计算属性 - 判断是否为语音模式(辅食除外)
const
isVoiceMode
=
computed
(()
=>
{
return
recordMethods
.
value
[
selectedType
.
value
]
===
'voice'
&&
selectedType
.
value
!==
'food'
})
})
// 计算属性 - 获取宝宝信息(只显示已出生的宝宝)
const
babyList
=
computed
(()
=>
{
// 计算属性 - 获取宝宝信息(只显示已出生的宝宝)
const
babyList
=
computed
(()
=>
{
const
allBabies
=
userStore
.
babyInfo
?.
allBabyBaseInfo
||
[]
// 只返回已出生的宝宝(babyStage === 2)
return
allBabies
.
filter
(
baby
=>
baby
.
babyStage
===
2
)
})
const
currentBabyIndex
=
computed
(()
=>
{
})
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
)
})
const
currentBaby
=
computed
(()
=>
userStore
.
babyInfo
?.
content
)
const
currentBabyId
=
computed
(()
=>
userStore
.
babyInfo
?.
content
?.
id
)
// 页面加载时获取数据
onMounted
(
async
()
=>
{
// 页面加载时获取数据
onMounted
(
async
()
=>
{
md
.
sensorLogTake
({
xcxPage
:
"小程序页面浏览事件"
,
pageName
:
"喂养工具首页"
,
...
...
@@ -760,18 +820,26 @@ onMounted(async () => {
// 初始化录音管理器
initializeRecorderManager
()
})
})
const
onRegisterConfirm
=
async
()
=>
{
isShowRegisterLayer
.
value
=
false
;
await
loadBabyInfo
()
loadFoodsData
()
// 初始化录音管理器
initializeRecorderManager
()
}
const
onPopupTipBabyChange
=
async
()
=>
{
const
onPopupTipBabyChange
=
async
()
=>
{
isTip
.
value
=
false
console
.
log
(
'onPopupTipBabyChange'
,
isTip
.
value
)
// showBabySwitchPopup.value = true
await
loadBabyInfo
()
loadHomeData
()
}
}
// 页面显示时刷新数据
onShow
(
async
()
=>
{
// 页面显示时刷新数据
onShow
(
async
()
=>
{
console
.
log
(
'页面显示,刷新数据...'
)
if
(
!
babyId
.
value
)
{
...
...
@@ -807,10 +875,10 @@ onShow(async () => {
restoreUnfinishedEdit
()
},
500
)
}
})
})
// 页面隐藏时同步计时器状态
onHide
(()
=>
{
// 页面隐藏时同步计时器状态
onHide
(()
=>
{
console
.
log
(
'页面隐藏,处理录音状态...'
)
// 如果正在录音,停止录音并重置状态
...
...
@@ -829,10 +897,10 @@ onHide(() => {
console
.
log
(
'页面隐藏时同步右侧计时器状态'
)
// 这里可以选择是否调用后端接口同步状态
}
})
})
// 页面卸载时清理计时器
onUnmounted
(()
=>
{
// 页面卸载时清理计时器
onUnmounted
(()
=>
{
console
.
log
(
'页面卸载,清理资源...'
)
// 清理左侧计时器
...
...
@@ -866,10 +934,10 @@ onUnmounted(() => {
}
catch
(
error
)
{
console
.
warn
(
'页面卸载时清理录音管理器回调出错:'
,
error
)
}
})
})
// 页面参数接收
onLoad
(
async
(
options
)
=>
{
// 页面参数接收
onLoad
(
async
(
options
)
=>
{
console
.
log
(
'页面参数:'
,
options
)
// 如果是修改记录,接收记录ID
...
...
@@ -894,18 +962,18 @@ onLoad(async (options) => {
}
selectedType
.
value
=
typeMap
[
options
.
feedingType
]
||
'breastfeeding'
}
})
})
function
getCurrentTime
()
{
function
getCurrentTime
()
{
const
now
=
new
Date
()
const
hours
=
String
(
now
.
getHours
()).
padStart
(
2
,
'0'
)
const
minutes
=
String
(
now
.
getMinutes
()).
padStart
(
2
,
'0'
)
return
`
${
hours
}
:
${
minutes
}
`
}
}
// 根据记录数据设置表单
function
setFormDataFromRecord
(
recordData
)
{
// 根据记录数据设置表单
function
setFormDataFromRecord
(
recordData
)
{
// 设置喂养类型
const
typeMap
=
{
1
:
'breastfeeding'
,
...
...
@@ -937,11 +1005,19 @@ function setFormDataFromRecord(recordData) {
}
// 不清除记录方法,保持用户的选择
}
}
// 获取宝宝信息
async
function
loadBabyInfo
()
{
// 获取宝宝信息
async
function
loadBabyInfo
()
{
try
{
isNotLogin
.
value
=
false
;
await
userStore
.
loadUserInfo
()
if
(
userStore
?.
userInfo
?.
memberId
&&
userStore
?.
userInfo
?.
memberId
==
"not_login"
||
!
userStore
.
userInfo
)
{
isNotLogin
.
value
=
true
;
}
console
.
log
(
'开始加载宝宝信息...'
)
if
(
userStore
.
babyInfo
?.
babyStage
!=
2
)
{
isTip
.
value
=
true
...
...
@@ -977,10 +1053,10 @@ async function loadBabyInfo() {
icon
:
'none'
})
}
}
}
// 获取首页数据
async
function
loadHomeData
()
{
// 获取首页数据
async
function
loadHomeData
()
{
if
(
!
babyId
.
value
)
{
isTip
.
value
=
true
return
...
...
@@ -1035,7 +1111,8 @@ async function loadHomeData() {
const
feedingResponse
=
await
fetchFeedingJSON
()
console
.
log
(
'轮播图数据:'
,
feedingResponse
)
if
(
feedingResponse
&&
feedingResponse
.
data
&&
feedingResponse
.
data
.
swiperData
&&
feedingResponse
.
data
.
swiperData
.
length
>
0
)
{
if
(
feedingResponse
&&
feedingResponse
.
data
&&
feedingResponse
.
data
.
swiperData
&&
feedingResponse
.
data
.
swiperData
.
length
>
0
)
{
swiperData
.
value
=
feedingResponse
.
data
.
swiperData
}
}
catch
(
error
)
{
...
...
@@ -1043,10 +1120,10 @@ async function loadHomeData() {
// 使用默认的轮播图数据作为fallback
swiperData
.
value
=
[]
}
}
}
// 根据接口数据初始化页面状态
function
initializePageData
()
{
// 根据接口数据初始化页面状态
function
initializePageData
()
{
const
data
=
homeData
.
value
// 设置当前时间,优先使用 home 接口的 timestamp
...
...
@@ -1112,10 +1189,10 @@ function initializePageData() {
// 重置计时器状态,确保状态和实际运行状态保持一致
resetTimerStatus
()
}
}
// 重置计时器状态
function
resetTimerStatus
()
{
// 重置计时器状态
function
resetTimerStatus
()
{
// 如果状态显示计时器在运行,但实际没有定时器在运行,则重置状态
if
(
isLeftTimerRunning
.
value
&&
!
leftTimerInterval
)
{
console
.
log
(
'重置左侧计时器状态:状态为运行但实际已停止'
)
...
...
@@ -1125,10 +1202,10 @@ function resetTimerStatus() {
console
.
log
(
'重置右侧计时器状态:状态为运行但实际已停止'
)
isRightTimerRunning
.
value
=
false
}
}
}
// 方法
function
selectType
(
type
)
{
// 方法
function
selectType
(
type
)
{
// 检查是否正在录音
if
(
recordingState
.
value
.
isRecording
||
voiceRecognitionState
.
value
.
isRecording
)
{
uni
.
showToast
({
...
...
@@ -1198,12 +1275,12 @@ function selectType(type) {
});
}
selectedType
.
value
=
type
}
}
// 清空之前的状态
function
clearPreviousState
()
{
// 清空之前的状态
function
clearPreviousState
()
{
// 清理轮询定时器
clearPollingInterval
()
...
...
@@ -1246,10 +1323,10 @@ function clearPreviousState() {
isDragging
.
value
=
false
startY
.
value
=
0
startAmount
.
value
=
0
}
}
// 清空喂养数据(保存成功后调用)
function
clearFeedingData
()
{
// 清空喂养数据(保存成功后调用)
function
clearFeedingData
()
{
// 清空所有喂养方式的数据
feedingData
.
value
.
breastfeeding
.
leftDuration
=
5
feedingData
.
value
.
breastfeeding
.
rightDuration
=
5
...
...
@@ -1316,9 +1393,9 @@ function clearFeedingData() {
}
console
.
log
(
'喂养数据已清空'
)
}
}
function
adjustDuration
(
side
,
value
)
{
function
adjustDuration
(
side
,
value
)
{
const
currentData
=
feedingData
.
value
.
breastfeeding
if
(
side
===
'left'
)
{
...
...
@@ -1365,26 +1442,26 @@ function adjustDuration(side, value) {
currentData
.
rightDuration
=
newValue
}
}
}
}
function
adjustAmount
(
value
)
{
function
adjustAmount
(
value
)
{
const
currentType
=
selectedType
.
value
if
(
currentType
===
'bottle'
||
currentType
===
'formula'
)
{
const
currentData
=
feedingData
.
value
[
currentType
]
currentData
.
amount
=
Math
.
max
(
0
,
Math
.
min
(
500
,
currentData
.
amount
+
value
))
}
}
}
// 滑动选择相关方法
function
onTouchStart
(
e
)
{
// 滑动选择相关方法
function
onTouchStart
(
e
)
{
isDragging
.
value
=
true
startY
.
value
=
e
.
touches
[
0
].
clientY
startAmount
.
value
=
feedingData
.
value
[
selectedType
.
value
].
amount
}
}
function
onTouchMove
(
e
)
{
function
onTouchMove
(
e
)
{
if
(
!
isDragging
.
value
)
return
const
currentY
=
e
.
touches
[
0
].
clientY
...
...
@@ -1398,26 +1475,26 @@ function onTouchMove(e) {
const
adjustedAmount
=
Math
.
round
(
newAmount
/
5
)
*
5
feedingData
.
value
[
selectedType
.
value
].
amount
=
adjustedAmount
}
}
function
onTouchEnd
()
{
function
onTouchEnd
()
{
isDragging
.
value
=
false
}
}
function
getSliderPosition
()
{
function
getSliderPosition
()
{
const
currentAmount
=
feedingData
.
value
[
selectedType
.
value
].
amount
// 将0-500ml映射到0-100%的位置
return
100
-
(
currentAmount
/
500
)
*
100
}
}
// picker-view选择事件
function
onPickerChange
(
e
)
{
// picker-view选择事件
function
onPickerChange
(
e
)
{
const
index
=
e
.
detail
.
value
[
0
]
const
selectedAmount
=
pickerAmounts
.
value
[
index
]
feedingData
.
value
[
selectedType
.
value
].
amount
=
selectedAmount
}
}
function
setRecordMethod
(
method
)
{
function
setRecordMethod
(
method
)
{
// 手动记录、计时器记录、语音记录
...
...
@@ -1489,7 +1566,8 @@ function setRecordMethod(method) {
}
// 母乳亲喂计时器运行时阻止切换记录方式
if
(
selectedType
.
value
===
'breastfeeding'
&&
((
isLeftTimerRunning
.
value
&&
leftTimerInterval
)
||
(
isRightTimerRunning
.
value
&&
rightTimerInterval
)))
{
if
(
selectedType
.
value
===
'breastfeeding'
&&
((
isLeftTimerRunning
.
value
&&
leftTimerInterval
)
||
(
isRightTimerRunning
.
value
&&
rightTimerInterval
)))
{
uni
.
showToast
({
title
:
'计时器正在运行,请先停止计时'
,
icon
:
'none'
...
...
@@ -1522,15 +1600,15 @@ function setRecordMethod(method) {
if
(
method
===
'voice'
)
{
checkVoicePermission
()
}
}
}
function
toggleRecording
()
{
function
toggleRecording
()
{
isRecording
.
value
=
!
isRecording
.
value
}
}
async
function
toggleTimer
(
side
)
{
async
function
toggleTimer
(
side
)
{
const
currentBabyId
=
babyId
.
value
if
(
side
===
'left'
)
{
...
...
@@ -1646,9 +1724,9 @@ async function toggleTimer(side) {
}
}
}
}
}
function
startLeftTimer
()
{
function
startLeftTimer
()
{
// 开始左侧计时
console
.
log
(
'开始左侧计时'
)
// 如果已经有计时器在运行,先停止
...
...
@@ -1667,18 +1745,18 @@ function startLeftTimer() {
autoStopLeftTimer
()
}
},
1000
)
// 每秒增加1秒
}
}
function
stopLeftTimer
()
{
function
stopLeftTimer
()
{
// 停止左侧计时
console
.
log
(
'停止左侧计时'
)
if
(
leftTimerInterval
)
{
clearInterval
(
leftTimerInterval
)
leftTimerInterval
=
null
}
}
}
function
startRightTimer
()
{
function
startRightTimer
()
{
// 开始右侧计时
console
.
log
(
'开始右侧计时'
)
// 如果已经有计时器在运行,先停止
...
...
@@ -1697,19 +1775,19 @@ function startRightTimer() {
autoStopRightTimer
()
}
},
1000
)
// 每秒增加1秒
}
}
function
stopRightTimer
()
{
function
stopRightTimer
()
{
// 停止右侧计时
console
.
log
(
'停止右侧计时'
)
if
(
rightTimerInterval
)
{
clearInterval
(
rightTimerInterval
)
rightTimerInterval
=
null
}
}
}
// 自动停止左侧计时器(调用后端接口)
async
function
autoStopLeftTimer
()
{
// 自动停止左侧计时器(调用后端接口)
async
function
autoStopLeftTimer
()
{
const
currentBabyId
=
babyId
.
value
if
(
!
currentBabyId
)
{
console
.
warn
(
'没有选择宝宝,无法停止计时器'
)
...
...
@@ -1727,10 +1805,10 @@ async function autoStopLeftTimer() {
console
.
error
(
'自动停止左侧计时器失败:'
,
error
)
// 不显示错误提示,因为这是自动停止
}
}
}
// 自动停止右侧计时器(调用后端接口)
async
function
autoStopRightTimer
()
{
// 自动停止右侧计时器(调用后端接口)
async
function
autoStopRightTimer
()
{
const
currentBabyId
=
babyId
.
value
if
(
!
currentBabyId
)
{
console
.
warn
(
'没有选择宝宝,无法停止计时器'
)
...
...
@@ -1748,10 +1826,10 @@ async function autoStopRightTimer() {
console
.
error
(
'自动停止右侧计时器失败:'
,
error
)
// 不显示错误提示,因为这是自动停止
}
}
}
// 停止所有计时器
async
function
stopAllTimers
()
{
// 停止所有计时器
async
function
stopAllTimers
()
{
const
currentBabyId
=
babyId
.
value
if
(
!
currentBabyId
)
{
console
.
warn
(
'没有选择宝宝,无法停止计时器'
)
...
...
@@ -1787,10 +1865,10 @@ async function stopAllTimers() {
// 不显示错误提示,因为这是正常的保存流程
// 即使计时器停止失败,也要继续保存记录
}
}
}
// 完成记录
async
function
completeRecord
()
{
// 完成记录
async
function
completeRecord
()
{
// 防止重复提交
...
...
@@ -1907,20 +1985,26 @@ async function completeRecord() {
isSubmitting
.
value
=
false
},
2000
)
}
}
}
// 验证记录数据
function
validateRecordData
()
{
// 验证记录数据
function
validateRecordData
()
{
const
currentBaby
=
userStore
.
babyInfo
?.
content
// 验证宝宝信息
if
(
!
currentBaby
||
!
currentBaby
.
id
)
{
return
{
valid
:
false
,
message
:
'请选择宝宝'
}
return
{
valid
:
false
,
message
:
'请选择宝宝'
}
}
// 验证喂养时间
if
(
!
currentTime
.
value
)
{
return
{
valid
:
false
,
message
:
'请选择喂养时间'
}
return
{
valid
:
false
,
message
:
'请选择喂养时间'
}
}
// 根据喂养类型和记录方式验证具体数据
...
...
@@ -1933,19 +2017,28 @@ function validateRecordData() {
const
leftDuration
=
feedingData
.
value
.
breastfeeding
.
leftDuration
const
rightDuration
=
feedingData
.
value
.
breastfeeding
.
rightDuration
if
(
leftDuration
===
0
&&
rightDuration
===
0
)
{
return
{
valid
:
false
,
message
:
'还没有输入喂养信息哦~'
}
return
{
valid
:
false
,
message
:
'还没有输入喂养信息哦~'
}
}
}
else
if
(
currentMethod
===
'timer'
)
{
// 计时器模式:验证计时器状态
const
leftDuration
=
timerData
.
value
.
leftDuration
const
rightDuration
=
timerData
.
value
.
rightDuration
if
(
leftDuration
===
0
&&
rightDuration
===
0
)
{
return
{
valid
:
false
,
message
:
'还没有输入喂养信息哦~'
}
return
{
valid
:
false
,
message
:
'还没有输入喂养信息哦~'
}
}
}
else
if
(
currentMethod
===
'voice'
)
{
// 语音模式:验证语音识别结果
if
(
!
voiceRecognitionState
.
value
.
recognizedText
.
trim
())
{
return
{
valid
:
false
,
message
:
'还没有输入喂养信息哦~'
}
return
{
valid
:
false
,
message
:
'还没有输入喂养信息哦~'
}
}
}
break
...
...
@@ -1958,12 +2051,18 @@ function validateRecordData() {
// 手动模式:验证喂养量
const
amount
=
feedingData
.
value
[
selectedType
.
value
].
amount
if
(
amount
===
0
)
{
return
{
valid
:
false
,
message
:
'还没有输入喂养信息哦~'
}
return
{
valid
:
false
,
message
:
'还没有输入喂养信息哦~'
}
}
}
else
if
(
currentMethod2
===
'voice'
)
{
// 语音模式:验证语音识别结果
if
(
!
voiceRecognitionState
.
value
.
recognizedText
.
trim
())
{
return
{
valid
:
false
,
message
:
'还没有输入喂养信息哦~'
}
return
{
valid
:
false
,
message
:
'还没有输入喂养信息哦~'
}
}
}
break
...
...
@@ -1972,16 +2071,21 @@ function validateRecordData() {
// 辅食只有手动选择模式
const
selectedItems
=
feedingData
.
value
.
food
.
selectedItems
if
(
selectedItems
.
length
===
0
)
{
return
{
valid
:
false
,
message
:
'还没有输入喂养信息哦~'
}
return
{
valid
:
false
,
message
:
'还没有输入喂养信息哦~'
}
}
break
}
return
{
valid
:
true
}
}
return
{
valid
:
true
}
}
// 构建记录数据
function
buildRecordData
()
{
// 构建记录数据
function
buildRecordData
()
{
const
currentBaby
=
userStore
.
babyInfo
?.
content
// 判断是否为语音模式,如果是则使用弹窗中的日期和时间
...
...
@@ -2020,7 +2124,8 @@ function buildRecordData() {
feedingType
:
1
,
// 母乳亲喂
durationLeftSeconds
:
feedingData
.
value
.
breastfeeding
.
leftDuration
*
60
,
// 转换为秒
durationRightSeconds
:
feedingData
.
value
.
breastfeeding
.
rightDuration
*
60
,
totalDurationSeconds
:
(
feedingData
.
value
.
breastfeeding
.
leftDuration
+
feedingData
.
value
.
breastfeeding
.
rightDuration
)
*
60
totalDurationSeconds
:
(
feedingData
.
value
.
breastfeeding
.
leftDuration
+
feedingData
.
value
.
breastfeeding
.
rightDuration
)
*
60
}
}
else
if
(
currentMethod
===
'timer'
)
{
// 计时器模式:使用计时器的实际时长
...
...
@@ -2091,13 +2196,13 @@ function buildRecordData() {
}
return
baseData
}
}
function
goBack
()
{
function
goBack
()
{
uni
.
navigateBack
()
}
}
function
goToFeedingRecord
()
{
function
goToFeedingRecord
()
{
// 检查是否正在录音
if
(
recordingState
.
value
.
isRecording
||
voiceRecognitionState
.
value
.
isRecording
)
{
uni
.
showToast
({
...
...
@@ -2116,15 +2221,15 @@ function goToFeedingRecord() {
uni
.
navigateTo
({
url
:
'/pages/feedingRecord/feedingRecord'
})
}
}
// 时间选择器相关方法
function
onTimeChange
(
value
)
{
// 时间选择器相关方法
function
onTimeChange
(
value
)
{
currentTime
.
value
=
value
}
}
// 语音识别时间选择器显示
function
showVoiceTimePicker
()
{
// 语音识别时间选择器显示
function
showVoiceTimePicker
()
{
// 使用与 formatCurrentTime() 一致的默认时间
if
(
!
voiceRecognitionState
.
value
.
voiceDateTime
)
{
const
defaultTimeString
=
formatCurrentTime
()
...
...
@@ -2136,10 +2241,10 @@ function showVoiceTimePicker() {
}
}
voiceTimePickerRef
.
value
.
show
()
}
}
// 语音识别时间选择
function
onVoiceTimeChange
(
value
)
{
// 语音识别时间选择
function
onVoiceTimeChange
(
value
)
{
// 设置完整的日期时间字符串
voiceRecognitionState
.
value
.
voiceDateTime
=
value
...
...
@@ -2154,10 +2259,10 @@ function onVoiceTimeChange(value) {
// 设置分离的日期和时间
voiceRecognitionState
.
value
.
recordDate
=
`
${
year
}
-
${
month
}
-
${
day
}
`
voiceRecognitionState
.
value
.
recordTime
=
`
${
hours
}
:
${
minutes
}
`
}
}
// 格式化语音识别时间显示
function
formatVoiceDateTime
()
{
// 格式化语音识别时间显示
function
formatVoiceDateTime
()
{
if
(
voiceRecognitionState
.
value
.
voiceDateTime
)
{
const
date
=
new
Date
(
voiceRecognitionState
.
value
.
voiceDateTime
)
const
year
=
date
.
getFullYear
()
...
...
@@ -2169,10 +2274,10 @@ function formatVoiceDateTime() {
return
`
${
year
}
-
${
month
}
-
${
day
}
${
hours
}
:
${
minutes
}
`
}
return
''
}
}
// 关闭语音识别结果弹窗
function
closeVoiceResult
()
{
// 关闭语音识别结果弹窗
function
closeVoiceResult
()
{
voiceRecognitionState
.
value
.
showResultPage
=
false
voiceRecognitionState
.
value
.
recognizedText
=
''
voiceRecognitionState
.
value
.
recordDate
=
''
...
...
@@ -2181,9 +2286,9 @@ function closeVoiceResult() {
// 重置防连点状态,确保用户可以重新录音
resetRecordingCooldown
()
}
}
function
formatCurrentTime
()
{
function
formatCurrentTime
()
{
if
(
!
currentTime
.
value
)
{
// 如果当前时间未设置,返回当前时间
const
now
=
new
Date
()
...
...
@@ -2202,9 +2307,9 @@ function formatCurrentTime() {
const
hours
=
String
(
date
.
getHours
()).
padStart
(
2
,
'0'
)
const
minutes
=
String
(
date
.
getMinutes
()).
padStart
(
2
,
'0'
)
return
`
${
year
}
-
${
month
}
-
${
day
}
${
hours
}
:
${
minutes
}
`
}
}
function
getTabImage
()
{
function
getTabImage
()
{
const
currentMethod
=
recordMethods
.
value
[
selectedType
.
value
]
if
(
currentMethod
===
'manual'
)
{
return
feedingIndexRes
.
Tab_bottom_write
...
...
@@ -2213,35 +2318,35 @@ function getTabImage() {
}
else
{
return
feedingIndexRes
.
Tab_bottom_voice
}
}
}
function
getTabImage2
()
{
function
getTabImage2
()
{
const
currentMethod
=
recordMethods
.
value
[
selectedType
.
value
]
if
(
currentMethod
===
'manual'
)
{
return
feedingIndexRes
.
Tab_bottom_muruandnaifen_write
}
else
{
return
feedingIndexRes
.
Tab_bottom_muruandnaifen_voice
}
}
}
// 格式化时间显示 (MM:SS)
function
formatTime
(
seconds
)
{
// 格式化时间显示 (MM:SS)
function
formatTime
(
seconds
)
{
const
minutes
=
Math
.
floor
(
seconds
/
60
)
const
remainingSeconds
=
seconds
%
60
return
`
${
minutes
.
toString
().
padStart
(
2
,
'0'
)}
:
${
remainingSeconds
.
toString
().
padStart
(
2
,
'0'
)}
`
}
}
// 格式化总时长显示 (HH:MM:SS)
function
formatTotalDuration
()
{
// 格式化总时长显示 (HH:MM:SS)
function
formatTotalDuration
()
{
const
totalSeconds
=
timerData
.
value
.
leftDuration
+
timerData
.
value
.
rightDuration
const
hours
=
Math
.
floor
(
totalSeconds
/
3600
)
const
minutes
=
Math
.
floor
((
totalSeconds
%
3600
)
/
60
)
const
seconds
=
totalSeconds
%
60
return
`
${
hours
.
toString
().
padStart
(
2
,
'0'
)}
:
${
minutes
.
toString
().
padStart
(
2
,
'0'
)}
:
${
seconds
.
toString
().
padStart
(
2
,
'0'
)}
`
}
}
// 辅食选择相关方法
function
toggleFoodSelection
(
item
)
{
// 辅食选择相关方法
function
toggleFoodSelection
(
item
)
{
// 在编辑模式时不允许选择
if
(
foodSelectionState
.
value
.
isEditMode
)
{
return
...
...
@@ -2257,9 +2362,9 @@ function toggleFoodSelection(item) {
// 如果未选中,则添加选中
selectedItems
.
push
(
item
)
}
}
}
function
enterEditMode
()
{
function
enterEditMode
()
{
if
(
foodSelectionState
.
value
.
isEditMode
)
{
// 如果已经在编辑模式,则取消编辑
cancelEditMode
()
...
...
@@ -2287,9 +2392,9 @@ function enterEditMode() {
// 清空待删除列表
foodSelectionState
.
value
.
pendingDeletes
=
[]
}
}
}
function
cancelEditMode
()
{
function
cancelEditMode
()
{
// 恢复原始辅食数据,保持原有顺序
if
(
foodSelectionState
.
value
.
originalFoodData
)
{
feedingData
.
value
.
food
.
selectedItems
=
[...
foodSelectionState
.
value
.
originalFoodData
.
selectedItems
]
...
...
@@ -2329,9 +2434,9 @@ function cancelEditMode() {
foodSelectionState
.
value
.
isEditMode
=
false
// 清理原始数据
foodSelectionState
.
value
.
originalFoodData
=
null
}
}
async
function
exitEditMode
()
{
async
function
exitEditMode
()
{
md
.
sensorLogTake
({
xcxClick
:
"小程序页面点击事件"
,
pageName
:
"喂养工具首页"
,
...
...
@@ -2381,7 +2486,8 @@ async function exitEditMode() {
if
(
foodSelectionState
.
value
.
originalFoodData
)
{
// 恢复原始辅食数据
Object
.
keys
(
foodCategories
.
value
).
forEach
(
categoryName
=>
{
const
originalCategory
=
foodSelectionState
.
value
.
originalFoodData
.
categories
[
categoryName
]
const
originalCategory
=
foodSelectionState
.
value
.
originalFoodData
.
categories
[
categoryName
]
if
(
originalCategory
)
{
foodCategories
.
value
[
categoryName
].
items
=
[...
originalCategory
.
items
]
foodCategories
.
value
[
categoryName
].
customItems
=
[...
originalCategory
.
customItems
]
...
...
@@ -2404,9 +2510,9 @@ async function exitEditMode() {
// 立即重置防连点状态
foodSelectionState
.
value
.
isDeletingFood
=
false
console
.
log
(
'防连点:重置删除完成状态为false'
)
}
}
function
showAddFoodPopup
(
categoryName
)
{
function
showAddFoodPopup
(
categoryName
)
{
md
.
sensorLogTake
({
xcxClick
:
"小程序页面点击事件"
,
pageName
:
"喂养工具首页"
,
...
...
@@ -2456,17 +2562,17 @@ function showAddFoodPopup(categoryName) {
foodSelectionState
.
value
.
isAddingFood
=
false
console
.
log
(
'防连点:重置添加辅食状态为false'
)
},
100
)
}
}
// 切换分类展开/缩起状态
function
toggleCategoryExpansion
(
categoryName
)
{
// 切换分类展开/缩起状态
function
toggleCategoryExpansion
(
categoryName
)
{
const
category
=
foodCategories
.
value
[
categoryName
]
if
(
category
)
{
category
.
expanded
=
!
category
.
expanded
}
}
}
function
cancelAddFood
()
{
function
cancelAddFood
()
{
addFoodPopup
.
value
.
close
()
foodSelectionState
.
value
.
newFoodItem
=
''
md
.
sensorPopLogTake
({
...
...
@@ -2475,9 +2581,9 @@ function cancelAddFood() {
popName
:
"新增辅食弹窗"
,
buttonName
:
"取消"
});
}
}
function
confirmAddFood
()
{
function
confirmAddFood
()
{
if
(
foodSelectionState
.
value
.
isAddingFood
)
{
console
.
log
(
'防连点:添加辅食按钮被阻止'
)
return
...
...
@@ -2511,9 +2617,9 @@ function confirmAddFood() {
foodSelectionState
.
value
.
isAddingFood
=
false
console
.
log
(
'防连点:重置添加辅食状态为false'
)
},
2000
)
}
}
async
function
addCustomFoodItem
(
categoryName
,
itemName
)
{
async
function
addCustomFoodItem
(
categoryName
,
itemName
)
{
// 检查字数限制
if
(
itemName
.
length
>
10
)
{
uni
.
showToast
({
...
...
@@ -2583,9 +2689,9 @@ async function addCustomFoodItem(categoryName, itemName) {
// 失败时重置防连点状态
foodSelectionState
.
value
.
isAddingFood
=
false
}
}
}
function
removeFoodItem
(
categoryName
,
itemName
)
{
function
removeFoodItem
(
categoryName
,
itemName
)
{
// 获取foodId
const
foodId
=
foodIdMap
.
value
.
get
(
itemName
)
...
...
@@ -2632,10 +2738,10 @@ function removeFoodItem(categoryName, itemName) {
})
console
.
log
(
'添加到待删除列表:'
,
itemName
,
'原始位置:'
,
originalIndex
,
'当前待删除:'
,
foodSelectionState
.
value
.
pendingDeletes
)
}
}
// 语音识别相关方法
function
checkVoicePermission
()
{
// 语音识别相关方法
function
checkVoicePermission
()
{
// 检查录音权限
uni
.
getSetting
({
success
:
(
res
)
=>
{
...
...
@@ -2662,13 +2768,16 @@ function checkVoicePermission() {
// 打开设置页面
uni
.
openSetting
({
success
:
(
settingRes
)
=>
{
console
.
log
(
'设置页面结果:'
,
settingRes
)
if
(
settingRes
.
authSetting
[
'scope.record'
])
{
console
.
log
(
'设置页面结果:'
,
settingRes
)
if
(
settingRes
.
authSetting
[
'scope.record'
])
{
console
.
log
(
'录音权限已开启'
)
}
},
fail
:
(
err
)
=>
{
console
.
error
(
'打开设置页面失败:'
,
err
)
console
.
error
(
'打开设置页面失败:'
,
err
)
}
})
}
...
...
@@ -2688,10 +2797,10 @@ function checkVoicePermission() {
})
}
})
}
}
// 录音状态管理
const
recordingState
=
ref
({
// 录音状态管理
const
recordingState
=
ref
({
isInitialized
:
false
,
// 是否已初始化录音管理器
isRecording
:
false
,
// 是否正在录音
recordingStartTime
:
null
,
// 录音开始时间
...
...
@@ -2699,10 +2808,10 @@ const recordingState = ref({
recordingTimer
:
null
,
// 录音时长定时器
lastStopTime
:
0
,
// 上次停止录音的时间戳
canStartRecording
:
true
// 是否可以开始录音(防连点)
})
})
// 初始化录音管理器(只初始化一次)
function
initializeRecorderManager
()
{
// 初始化录音管理器(只初始化一次)
function
initializeRecorderManager
()
{
if
(
recordingState
.
value
.
isInitialized
)
{
console
.
log
(
'录音管理器已初始化,跳过'
)
return
...
...
@@ -2745,7 +2854,8 @@ function initializeRecorderManager() {
// 启动录音时长定时器
recordingState
.
value
.
recordingTimer
=
setInterval
(()
=>
{
if
(
recordingState
.
value
.
isRecording
&&
recordingState
.
value
.
recordingStartTime
)
{
const
duration
=
Math
.
floor
((
Date
.
now
()
-
recordingState
.
value
.
recordingStartTime
)
/
1000
)
const
duration
=
Math
.
floor
((
Date
.
now
()
-
recordingState
.
value
.
recordingStartTime
)
/
1000
)
recordingState
.
value
.
recordingDuration
=
duration
voiceRecognitionState
.
value
.
recordingDuration
=
duration
}
...
...
@@ -2830,10 +2940,10 @@ function initializeRecorderManager() {
recordingState
.
value
.
isInitialized
=
true
console
.
log
(
'录音管理器初始化完成'
)
}
}
// 重置录音状态
function
resetRecordingState
()
{
// 重置录音状态
function
resetRecordingState
()
{
console
.
log
(
'重置录音状态'
)
// 清理录音定时器
...
...
@@ -2855,26 +2965,26 @@ function resetRecordingState() {
// 注意:这里不调用 recorderManager.stop(),因为调用方会处理
// 避免重复调用导致的问题
}
}
// 重置防连点状态(立即恢复)
function
resetRecordingCooldown
()
{
// 重置防连点状态(立即恢复)
function
resetRecordingCooldown
()
{
recordingState
.
value
.
canStartRecording
=
true
console
.
log
(
'立即重置录音冷却状态'
)
}
}
// 检查录音管理器状态
function
checkRecorderStatus
()
{
// 检查录音管理器状态
function
checkRecorderStatus
()
{
console
.
log
(
'检查录音管理器状态:'
,
{
isRecording
:
recordingState
.
value
.
isRecording
,
voiceIsRecording
:
voiceRecognitionState
.
value
.
isRecording
,
recognitionStatus
:
voiceRecognitionState
.
value
.
recognitionStatus
,
canStartRecording
:
recordingState
.
value
.
canStartRecording
})
}
}
// 强制重置录音管理器状态
function
forceResetRecorderManager
()
{
// 强制重置录音管理器状态
function
forceResetRecorderManager
()
{
console
.
log
(
'强制重置录音管理器状态'
)
// 重置录音状态
...
...
@@ -2902,10 +3012,10 @@ function forceResetRecorderManager() {
// 检查重置后的状态
checkRecorderStatus
()
},
300
)
}
}
// 开始录音
async
function
startRecording
()
{
// 开始录音
async
function
startRecording
()
{
if
(
!
recordingState
.
value
.
isRecording
)
{
md
.
sensorLogTake
({
xcxClick
:
"小程序页面点击事件"
,
...
...
@@ -3008,10 +3118,10 @@ async function startRecording() {
})
}
})
}
}
// 停止录音
async
function
stopRecording
()
{
// 停止录音
async
function
stopRecording
()
{
console
.
log
(
'停止录音请求...'
)
...
...
@@ -3076,10 +3186,10 @@ async function stopRecording() {
// 即使停止失败,也要强制重置录音管理器状态
forceResetRecorderManager
()
}
}
}
// 处理语音文件
async
function
processVoiceFile
(
tempFilePath
)
{
// 处理语音文件
async
function
processVoiceFile
(
tempFilePath
)
{
try
{
// 显示加载提示
uni
.
showLoading
({
...
...
@@ -3097,10 +3207,10 @@ async function processVoiceFile(tempFilePath) {
}
catch
(
error
)
{
handleVoiceRecognitionError
(
error
)
}
}
}
// 上传语音文件
async
function
uploadVoiceFile
(
tempFilePath
)
{
// 上传语音文件
async
function
uploadVoiceFile
(
tempFilePath
)
{
return
new
Promise
((
resolve
,
reject
)
=>
{
// 检查文件路径
if
(
!
tempFilePath
||
typeof
tempFilePath
!==
'string'
)
{
...
...
@@ -3144,38 +3254,50 @@ async function uploadVoiceFile(tempFilePath) {
encoding
:
'base64'
,
success
:
async
(
res
)
=>
{
try
{
console
.
log
(
'语音文件读取成功,base64长度:'
,
res
.
data
.
length
,
'字符'
)
console
.
log
(
'语音文件读取成功,base64长度:'
,
res
.
data
.
length
,
'字符'
)
// 检查base64数据是否有效
if
(
!
res
.
data
||
res
.
data
.
length
<
100
)
{
console
.
error
(
'base64数据无效,长度:'
,
res
.
data
?.
length
)
reject
(
new
Error
(
'语音文件数据无效,请重新录音'
))
if
(
!
res
.
data
||
res
.
data
.
length
<
100
)
{
console
.
error
(
'base64数据无效,长度:'
,
res
.
data
?.
length
)
reject
(
new
Error
(
'语音文件数据无效,请重新录音'
))
return
}
// 验证base64格式
if
(
!
/^
[
A-Za-z0-9+
/]
*=
{0,2}
$/
.
test
(
res
.
data
))
{
if
(
!
/^
[
A-Za-z0-9+
/]
*=
{0,2}
$/
.
test
(
res
.
data
))
{
console
.
error
(
'base64格式无效'
)
reject
(
new
Error
(
'语音文件格式无效,请重新录音'
))
reject
(
new
Error
(
'语音文件格式无效,请重新录音'
))
return
}
console
.
log
(
'base64数据验证通过,开始上传'
)
// 添加base64格式头
const
base64WithHeader
=
`data:audio/mp3;base64,
${
res
.
data
}
`
const
base64WithHeader
=
`data:audio/mp3;base64,
${
res
.
data
}
`
// 调用上传接口,传递带格式头的base64数据
const
response
=
await
feedingVoiceUpload
({
const
response
=
await
feedingVoiceUpload
({
audioData
:
base64WithHeader
})
console
.
log
(
'上传接口返回:'
,
response
)
if
(
response
&&
response
.
data
&&
response
.
data
.
taskId
)
{
if
(
response
&&
response
.
data
&&
response
.
data
.
taskId
)
{
resolve
(
response
.
data
)
}
else
{
reject
(
new
Error
(
'上传失败:未获取到taskId,返回数据:'
+
JSON
.
stringify
(
response
)))
reject
(
new
Error
(
'上传失败:未获取到taskId,返回数据:'
+
JSON
.
stringify
(
response
)))
}
}
catch
(
error
)
{
console
.
error
(
'上传过程中发生错误:'
,
error
)
...
...
@@ -3184,7 +3306,8 @@ async function uploadVoiceFile(tempFilePath) {
},
fail
:
(
err
)
=>
{
console
.
error
(
'读取语音文件失败:'
,
err
)
reject
(
new
Error
(
'读取语音文件失败:'
+
err
.
errMsg
))
reject
(
new
Error
(
'读取语音文件失败:'
+
err
.
errMsg
))
}
})
},
...
...
@@ -3200,10 +3323,10 @@ async function uploadVoiceFile(tempFilePath) {
}
})
})
}
}
// 开始轮询识别结果
async
function
startPollingRecognitionResult
(
taskId
)
{
// 开始轮询识别结果
async
function
startPollingRecognitionResult
(
taskId
)
{
console
.
log
(
'开始轮询识别结果,taskId:'
,
taskId
)
voiceRecognitionState
.
value
.
taskId
=
taskId
...
...
@@ -3266,7 +3389,8 @@ async function startPollingRecognitionResult(taskId) {
voiceRecognitionState
.
value
.
recordDate
=
`
${
year
}
-
${
month
}
-
${
day
}
`
voiceRecognitionState
.
value
.
recordTime
=
`
${
hours
}
:
${
minutes
}
`
voiceRecognitionState
.
value
.
voiceDateTime
=
`
${
year
}
-
${
month
}
-
${
day
}
${
hours
}
:
${
minutes
}
:00`
voiceRecognitionState
.
value
.
voiceDateTime
=
`
${
year
}
-
${
month
}
-
${
day
}
${
hours
}
:
${
minutes
}
:00`
}
voiceRecognitionState
.
value
.
showResultPage
=
true
md
.
sensorPopLogTake
({
...
...
@@ -3340,10 +3464,10 @@ async function startPollingRecognitionResult(taskId) {
})
}
},
30000
)
}
}
// 清理轮询定时器
function
clearPollingInterval
()
{
// 清理轮询定时器
function
clearPollingInterval
()
{
console
.
log
(
'清理轮询定时器'
)
if
(
voiceRecognitionState
.
value
.
pollingInterval
)
{
...
...
@@ -3369,10 +3493,10 @@ function clearPollingInterval() {
// 重置防连点状态,确保用户可以重新录音
resetRecordingCooldown
()
}
}
// 处理语音识别错误
function
handleVoiceRecognitionError
(
error
)
{
// 处理语音识别错误
function
handleVoiceRecognitionError
(
error
)
{
console
.
error
(
'语音识别错误:'
,
error
)
clearPollingInterval
()
uni
.
hideLoading
()
...
...
@@ -3401,9 +3525,9 @@ function handleVoiceRecognitionError(error) {
title
:
errorMessage
,
icon
:
'none'
})
}
}
function
getFeedingTypeLabel
()
{
function
getFeedingTypeLabel
()
{
const
typeMap
=
{
breastfeeding
:
'母乳亲喂'
,
bottle
:
'母乳瓶喂'
,
...
...
@@ -3411,10 +3535,10 @@ function getFeedingTypeLabel() {
food
:
'辅食'
}
return
typeMap
[
selectedType
.
value
]
||
'未知'
}
}
// 格式化录音时长显示
function
formatRecordingDuration
(
seconds
)
{
// 格式化录音时长显示
function
formatRecordingDuration
(
seconds
)
{
if
(
!
seconds
||
seconds
<=
0
)
return
'0秒'
const
minutes
=
Math
.
floor
(
seconds
/
60
)
...
...
@@ -3425,9 +3549,9 @@ function formatRecordingDuration(seconds) {
}
else
{
return
`
${
remainingSeconds
}
秒`
}
}
}
function
reRecognize
()
{
function
reRecognize
()
{
console
.
log
(
'重新识别...'
)
md
.
sensorPopLogTake
({
xcxPopClick
:
"true"
,
...
...
@@ -3454,9 +3578,9 @@ function reRecognize() {
voiceRecognitionState
.
value
.
recordDate
=
''
voiceRecognitionState
.
value
.
recordTime
=
''
voiceRecognitionState
.
value
.
voiceDateTime
=
''
}
}
async
function
completeVoiceRecord
()
{
async
function
completeVoiceRecord
()
{
// 防止重复提交
if
(
isSubmitting
.
value
)
{
return
...
...
@@ -3542,12 +3666,12 @@ async function completeVoiceRecord() {
isSubmitting
.
value
=
false
},
2000
)
}
}
}
// 记录成功弹窗相关方法
async
function
onSuccessJump
()
{
// 记录成功弹窗相关方法
async
function
onSuccessJump
()
{
// 检查是否正在录音
if
(
recordingState
.
value
.
isRecording
||
voiceRecognitionState
.
value
.
isRecording
)
{
uni
.
showToast
({
...
...
@@ -3567,7 +3691,13 @@ async function onSuccessJump() {
return
;
}
const
{
sign
,
timestamp
,
appId
,
partnerUserId
,
env
}
=
res
.
data
;
const
{
sign
,
timestamp
,
appId
,
partnerUserId
,
env
}
=
res
.
data
;
jump
({
type
:
JumpType
.
MINI
,
...
...
@@ -3580,8 +3710,7 @@ async function onSuccessJump() {
timestamp
,
// 参考 4.请求参数
appId
,
// 参考 4.请求参数
partnerUserId
,
// 参考 4.请求参数
targetApp
:
"/h5/partner/shining-like-a-start/landing-free-consult?sysType=CRF"
,
targetApp
:
"/h5/partner/shining-like-a-start/landing-free-consult?sysType=CRF"
,
},
},
});
// 关闭弹窗
...
...
@@ -3592,9 +3721,9 @@ async function onSuccessJump() {
popName
:
"添加成功弹窗"
,
buttonName
:
"咨询专家"
});
}
}
function
onSuccessClose
()
{
function
onSuccessClose
()
{
// 关闭弹窗
successPopup
.
value
.
close
()
md
.
sensorPopLogTake
({
...
...
@@ -3607,15 +3736,15 @@ function onSuccessClose() {
uni
.
navigateTo
({
url
:
'/pages/feedingRecord/feedingRecord'
})
}
}
// 检查是否有未完成的编辑操作
function
hasUnfinishedEdit
()
{
// 检查是否有未完成的编辑操作
function
hasUnfinishedEdit
()
{
return
foodSelectionState
.
value
.
isEditMode
&&
foodSelectionState
.
value
.
pendingDeletes
.
length
>
0
}
}
// 恢复未完成的编辑操作
function
restoreUnfinishedEdit
()
{
// 恢复未完成的编辑操作
function
restoreUnfinishedEdit
()
{
if
(
hasUnfinishedEdit
())
{
console
.
log
(
'恢复未完成的辅食删除操作'
)
// 显示提示
...
...
@@ -3636,10 +3765,10 @@ function restoreUnfinishedEdit() {
}
})
}
}
}
// 宝宝切换相关方法
function
showBabySwitch
()
{
// 宝宝切换相关方法
function
showBabySwitch
()
{
// 检查是否正在录音
if
(
recordingState
.
value
.
isRecording
||
voiceRecognitionState
.
value
.
isRecording
)
{
uni
.
showToast
({
...
...
@@ -3658,9 +3787,9 @@ function showBabySwitch() {
});
showBabySwitchPopup
.
value
=
true
}
}
}
async
function
onBabyChange
(
baby
,
index
)
{
async
function
onBabyChange
(
baby
,
index
)
{
// 切换宝宝
await
userStore
.
changeBabySelected
(
baby
.
id
)
console
.
log
(
'切换到宝宝:'
,
baby
.
babyName
,
'索引:'
,
index
)
...
...
@@ -3670,17 +3799,23 @@ async function onBabyChange(baby, index) {
// 清空当前状态,避免数据混乱
clearPreviousState
()
}
}
// 获取辅食列表数据
async
function
loadFoodsData
()
{
// 获取辅食列表数据
async
function
loadFoodsData
()
{
try
{
const
response
=
await
feedingFoodsCustom
()
console
.
log
(
'辅食列表数据:'
,
response
)
if
(
response
&&
response
.
data
)
{
const
foodsList
=
response
.
data
//未登录情况下这里是个object{error_msg:'404 Route Not Found'}
if
(
foodsList
instanceof
Array
)
{
processFoodsData
(
foodsList
)
}
else
{
processFoodsData
([])
}
}
else
{
// 如果没有数据,使用默认数据
loadDefaultFoodsData
()
...
...
@@ -3691,10 +3826,10 @@ async function loadFoodsData() {
// 使用默认数据作为fallback
loadDefaultFoodsData
()
}
}
}
// 处理辅食数据
function
processFoodsData
(
foodsList
)
{
// 处理辅食数据
function
processFoodsData
(
foodsList
)
{
// 清空现有数据
Object
.
keys
(
foodCategories
.
value
).
forEach
(
category
=>
{
foodCategories
.
value
[
category
].
items
=
[]
...
...
@@ -3719,10 +3854,10 @@ function processFoodsData(foodsList) {
console
.
log
(
'处理后的辅食数据:'
,
foodCategories
.
value
)
console
.
log
(
'辅食ID映射:'
,
foodIdMap
.
value
)
}
}
// 加载默认辅食数据(fallback)
function
loadDefaultFoodsData
()
{
// 加载默认辅食数据(fallback)
function
loadDefaultFoodsData
()
{
foodCategories
.
value
=
{
主食
:
{
items
:
[],
...
...
@@ -3745,48 +3880,48 @@ function loadDefaultFoodsData() {
expanded
:
false
}
}
}
}
onShareAppMessage
(()
=>
{
onShareAppMessage
(()
=>
{
return
{
title
:
"喂养记录:喂奶辅食轻松记录,喂养数据一目了然"
,
path
:
"/pages/feedingIndex/feedingIndex"
,
imageUrl
:
$baseUrl
+
"share/weiyang.png"
,
}
});
});
onShareTimeline
(()
=>
{
onShareTimeline
(()
=>
{
return
{
title
:
"喂养记录:喂奶辅食轻松记录,喂养数据一目了然"
,
path
:
"/pages/feedingIndex/feedingIndex"
,
imageUrl
:
$baseUrl
+
"share/weiyang.png"
,
}
});
});
</
script
>
<
style
lang=
"scss"
scoped
>
/* ===== 页面整体布局 ===== */
.feeding-record-add-page
{
/* ===== 页面整体布局 ===== */
.feeding-record-add-page
{
background
:
#ffffff
;
min-height
:
100vh
;
padding
:
0
;
position
:
relative
;
}
/* ===== 可滚动内容区域 ===== */
// .scrollable-content {
// height: calc(100vh);
// // height: 100vh;
// background-color: #FFF8F1;
// /* 减去底部按钮的高度 */
// z-index: 200;
// position: absolute;
// width: 100vw;
// }
/* ===== 底部完成按钮 ===== */
.bottom_complete-btn
{
}
/* ===== 可滚动内容区域 ===== */
// .scrollable-content {
// height: calc(100vh);
// // height: 100vh;
// background-color: #FFF8F1;
// /* 减去底部按钮的高度 */
// z-index: 200;
// position: absolute;
// width: 100vw;
// }
/* ===== 底部完成按钮 ===== */
.bottom_complete-btn
{
// padding-top: 20rpx;
position
:
fixed
;
bottom
:
0rpx
;
...
...
@@ -3805,10 +3940,10 @@ onShareTimeline(() => {
height
:
94rpx
;
display
:
block
;
}
}
}
/* ===== 广告横幅 ===== */
.banner-swiper
{
/* ===== 广告横幅 ===== */
.banner-swiper
{
position
:
relative
;
top
:
0
;
left
:
16rpx
;
...
...
@@ -3820,10 +3955,10 @@ onShareTimeline(() => {
height
:
100%
;
border-radius
:
16rpx
;
}
}
}
/* ===== 喂养时间区域 ===== */
.feeding-time
{
/* ===== 喂养时间区域 ===== */
.feeding-time
{
position
:
relative
;
// margin-top: 174rpx;
left
:
0
;
...
...
@@ -3908,10 +4043,10 @@ onShareTimeline(() => {
margin-top
:
10rpx
;
}
}
}
}
/* ===== 喂养记录链接 ===== */
.feeding-records
{
/* ===== 喂养记录链接 ===== */
.feeding-records
{
position
:
relative
;
// margin-top: 270rpx;
left
:
0
;
...
...
@@ -3937,12 +4072,12 @@ onShareTimeline(() => {
width
:
11rpx
;
height
:
19rpx
;
}
}
}
/* ===== 喂养类型选择 ===== */
.feeding-types
{
/* ===== 喂养类型选择 ===== */
.feeding-types
{
position
:
relative
;
// margin-top: 320rpx;
left
:
0
;
...
...
@@ -4007,10 +4142,10 @@ onShareTimeline(() => {
}
}
}
}
}
/* ===== 温馨提示 ===== */
.warm-tip
{
/* ===== 温馨提示 ===== */
.warm-tip
{
position
:
relative
;
// margin-top: 20rpx;
left
:
0
;
...
...
@@ -4023,10 +4158,10 @@ onShareTimeline(() => {
font-size
:
24rpx
;
color
:
#000
;
}
}
}
/* ===== 表单区域 ===== */
.form-section
{
/* ===== 表单区域 ===== */
.form-section
{
position
:
absolute
;
top
:
80rpx
;
left
:
0
;
...
...
@@ -4036,10 +4171,10 @@ onShareTimeline(() => {
background-color
:
#fff
;
// height: 300rpx;
z-index
:
2
;
}
}
/* ===== 母乳亲喂表单 ===== */
.breastfeeding-form
{
/* ===== 母乳亲喂表单 ===== */
.breastfeeding-form
{
.duration-controls
{
display
:
flex
;
...
...
@@ -4124,10 +4259,10 @@ onShareTimeline(() => {
}
}
}
}
}
/* ===== 母乳瓶喂/奶粉喂养表单 ===== */
.bottle-form
{
/* ===== 母乳瓶喂/奶粉喂养表单 ===== */
.bottle-form
{
.bottle-graphic
{
width
:
100%
;
height
:
574rpx
;
...
...
@@ -4234,10 +4369,10 @@ onShareTimeline(() => {
}
}
}
}
/* ===== 辅食表单 ===== */
.food-form
{
/* ===== 辅食表单 ===== */
.food-form
{
margin-top
:
-80rpx
;
.selected-items
{
...
...
@@ -4451,14 +4586,14 @@ onShareTimeline(() => {
}
}
}
}
}
/* ===== 添加辅食弹窗 ===== */
.add-food-popup-container
{
/* ===== 添加辅食弹窗 ===== */
.add-food-popup-container
{
z-index
:
10003
!
important
;
}
}
.add-food-popup
{
.add-food-popup
{
background
:
white
;
border-radius
:
40rpx
;
width
:
654rpx
;
...
...
@@ -4531,12 +4666,12 @@ onShareTimeline(() => {
}
}
}
}
}
/* ===== 记录成功弹窗 ===== */
.success-popup
{
/* ===== 记录成功弹窗 ===== */
.success-popup
{
position
:
relative
;
width
:
654rpx
;
height
:
436rpx
;
...
...
@@ -4588,10 +4723,10 @@ onShareTimeline(() => {
}
}
}
}
/* ===== 记录方式选择 ===== */
.record-methods1
{
/* ===== 记录方式选择 ===== */
.record-methods1
{
position
:
absolute
;
top
:
570rpx
;
left
:
0
;
...
...
@@ -4625,10 +4760,10 @@ onShareTimeline(() => {
.right
{
left
:
calc
(
50%
+
78rpx
);
}
}
}
/* ===== 记录方式选择 - 母乳瓶喂/奶粉喂养 ===== */
.record-methods2
{
/* ===== 记录方式选择 - 母乳瓶喂/奶粉喂养 ===== */
.record-methods2
{
position
:
absolute
;
top
:
570rpx
;
left
:
0
;
...
...
@@ -4680,10 +4815,10 @@ onShareTimeline(() => {
font-weight
:
bold
;
}
}
}
}
/* ===== 语音控制区域 ===== */
.voice-controls
{
/* ===== 语音控制区域 ===== */
.voice-controls
{
position
:
absolute
;
left
:
0
;
right
:
0
;
...
...
@@ -4741,10 +4876,10 @@ onShareTimeline(() => {
color
:
#6f6d67
;
}
}
}
}
/* ===== 计时器控制区域 ===== */
.timer-controls
{
/* ===== 计时器控制区域 ===== */
.timer-controls
{
position
:
absolute
;
left
:
0
;
right
:
0
;
...
...
@@ -4808,13 +4943,13 @@ onShareTimeline(() => {
}
}
}
}
}
/* ===== 下半部分背景区域 ===== */
.bottom-section
{
/* ===== 下半部分背景区域 ===== */
.bottom-section
{
position
:
relative
;
left
:
0
;
right
:
0
;
...
...
@@ -4834,37 +4969,37 @@ onShareTimeline(() => {
}
}
// uni-datetime-picker样式覆盖(与feedingRecord页面保持一致)
::v-deep
.uni-datetime-picker--btn
{
// uni-datetime-picker样式覆盖(与feedingRecord页面保持一致)
::v-deep
.uni-datetime-picker--btn
{
background-color
:
#D4A574
!
important
;
}
}
::v-deep
.uni-calendar-item--checked
{
::v-deep
.uni-calendar-item--checked
{
background-color
:
#D4A574
!
important
;
}
}
::v-deep
.uni-datetime-picker-btn-text
{
::v-deep
.uni-datetime-picker-btn-text
{
color
:
#D4A574
!
important
;
}
}
/* 全局时间选择器层级修复 */
::v-deep
.uni-datetime-picker
{
/* 全局时间选择器层级修复 */
::v-deep
.uni-datetime-picker
{
z-index
:
999999
!
important
;
}
}
::v-deep
.uni-datetime-picker__mask
{
::v-deep
.uni-datetime-picker__mask
{
z-index
:
999998
!
important
;
position
:
fixed
!
important
;
top
:
0
!
important
;
left
:
0
!
important
;
right
:
0
!
important
;
bottom
:
0
!
important
;
}
}
::v-deep
.uni-datetime-picker__popup
{
::v-deep
.uni-datetime-picker__popup
{
z-index
:
999999
!
important
;
position
:
fixed
!
important
;
bottom
:
218rpx
!
important
;
...
...
@@ -4874,66 +5009,66 @@ onShareTimeline(() => {
padding
:
30px
!
important
;
width
:
270px
!
important
;
background-color
:
#fff
!
important
;
}
}
::v-deep
.uni-datetime-picker__content
{
::v-deep
.uni-datetime-picker__content
{
z-index
:
999999
!
important
;
position
:
relative
!
important
;
}
}
/* 确保时间选择器内部元素也有正确的层级 */
::v-deep
.uni-datetime-picker__container
{
/* 确保时间选择器内部元素也有正确的层级 */
::v-deep
.uni-datetime-picker__container
{
z-index
:
999999
!
important
;
position
:
relative
!
important
;
}
}
::v-deep
.uni-datetime-picker__timebox
{
::v-deep
.uni-datetime-picker__timebox
{
z-index
:
999999
!
important
;
position
:
relative
!
important
;
}
}
::v-deep
.uni-datetime-picker__date
{
::v-deep
.uni-datetime-picker__date
{
z-index
:
999999
!
important
;
position
:
relative
!
important
;
}
}
::v-deep
.uni-datetime-picker__time
{
::v-deep
.uni-datetime-picker__time
{
z-index
:
999999
!
important
;
position
:
relative
!
important
;
}
}
/* 修复时间选择器文本显示位置 */
::v-deep
.uni-datetime-picker-text
{
/* 修复时间选择器文本显示位置 */
::v-deep
.uni-datetime-picker-text
{
position
:
relative
!
important
;
display
:
inline-block
!
important
;
line-height
:
50px
!
important
;
font-size
:
14px
!
important
;
text-align
:
center
!
important
;
vertical-align
:
middle
!
important
;
}
}
/* 修复时间选择器内部布局 */
::v-deep
.uni-datetime-picker__container-box
{
/* 修复时间选择器内部布局 */
::v-deep
.uni-datetime-picker__container-box
{
position
:
relative
!
important
;
display
:
flex
!
important
;
align-items
:
center
!
important
;
justify-content
:
center
!
important
;
margin-top
:
40px
!
important
;
}
}
::v-deep
.uni-datetime-picker-item
{
::v-deep
.uni-datetime-picker-item
{
display
:
flex
!
important
;
align-items
:
center
!
important
;
justify-content
:
center
!
important
;
height
:
50px
!
important
;
}
}
::v-deep
.uni-datetime-picker-view
{
::v-deep
.uni-datetime-picker-view
{
height
:
150px
!
important
;
}
}
/* ===== 语音识别结果弹窗 ===== */
.popup-mask
{
/* ===== 语音识别结果弹窗 ===== */
.popup-mask
{
position
:
fixed
;
top
:
0
;
left
:
0
;
...
...
@@ -4947,11 +5082,11 @@ onShareTimeline(() => {
overflow
:
hidden
;
touch-action
:
none
;
/* 为固定按钮留出空间 */
}
}
.popup-content
{
.popup-content
{
background
:
#f6f8fa
;
width
:
750rpx
;
max-height
:
80vh
;
...
...
@@ -5156,9 +5291,9 @@ onShareTimeline(() => {
padding-top
:
20rpx
!
important
;
border-top
:
1rpx
solid
#e5e5e5
!
important
;
}
}
}
@keyframes
slideUp
{
@keyframes
slideUp
{
from
{
transform
:
translateY
(
100%
);
}
...
...
@@ -5166,10 +5301,10 @@ onShareTimeline(() => {
to
{
transform
:
translateY
(
0
);
}
}
}
// 语音模式提示样式
.voice-mode-tip
{
// 语音模式提示样式
.voice-mode-tip
{
position
:
absolute
;
top
:
-60rpx
;
left
:
50%
;
...
...
@@ -5181,15 +5316,15 @@ onShareTimeline(() => {
font-size
:
24rpx
;
white-space
:
nowrap
;
z-index
:
10
;
}
}
.
food-input
:
:
placeholder
{
.
food-input
:
:
placeholder
{
color
:
#bbb
;
line-height
:
70rpx
;
/* 或 110rpx,和上面保持一致 */
}
}
.uni-date
{
.uni-date
{
z-index
:
999999
!
important
;
}
}
</
style
>
\ No newline at end of file
pages/postnatalCheckUp/postnatalCheckUp.vue
View file @
40699575
...
...
@@ -114,7 +114,9 @@
</view>
<!-- 提示弹窗 -->
<popup-tip
v-if=
"isTip"
type=
"2"
@
statusChange=
"onBabyChange"
@
close=
"isTip = false"
></popup-tip>
<popup-tip
v-if=
"isTip"
type=
"2"
@
statusChange=
"onBabyChange"
@
afterPhone=
"isShowRegisterLayer = true"
:isNotLogin=
"isNotLogin"
@
close=
"isTip = false"
></popup-tip>
<RegisterLayer
v-model=
"isShowRegisterLayer"
@
confirm=
"onRegisterConfirm"
/>
<!-- 使用封装后的日期选择器组件 -->
<DatePicker
v-model:visible=
"visible"
:default-date=
"time"
@
confirm=
"handleDateConfirm"
/>
...
...
@@ -151,6 +153,7 @@ import {
}
from
'../../api/obstetric.js'
;
// 导入日期选择器组件
import
DatePicker
from
'@/components/DatePicker.vue'
import
RegisterLayer
from
'@/components/RegisterLayer.vue'
const
{
proxy
}
=
getCurrentInstance
();
...
...
@@ -169,6 +172,8 @@ const isWxNotification = ref(true)
// 提示弹窗
const
isTip
=
ref
(
false
)
const
isNotLogin
=
ref
(
false
);
const
isShowRegisterLayer
=
ref
(
false
)
// 弹窗控制
const
showPicker
=
ref
(
false
)
...
...
@@ -563,8 +568,19 @@ const onBabyChange = () => {
publicFn
()
}
// 公共函数
const
publicFn
=
()
=>
{
console
.
log
(
"🚀 ~ onShow ~ userStore:"
,
userStore
.
babyInfo
)
const
publicFn
=
async
()
=>
{
await
userStore
.
loadUserInfo
()
console
.
log
(
"🚀 ~ onShow ~ userStore:"
,
userStore
.
userInfo
)
isNotLogin
.
value
=
false
;
if
(
userStore
?.
userInfo
?.
memberId
&&
userStore
?.
userInfo
?.
memberId
==
"not_login"
||
!
userStore
.
userInfo
)
{
isNotLogin
.
value
=
true
;
}
const
babyInfo
=
userStore
.
babyInfo
if
(
babyInfo
&&
babyInfo
.
babyStage
==
1
)
{
isTip
.
value
=
false
...
...
@@ -578,6 +594,11 @@ const publicFn = () => {
isTip
.
value
=
true
}
}
const
onRegisterConfirm
=
async
()
=>
{
isShowRegisterLayer
.
value
=
false
;
await
userStore
.
loadBabyInfo
()
publicFn
()
}
onShow
(
async
()
=>
{
await
userStore
.
loadBabyInfo
()
console
.
log
(
'宝宝信息加载完成:'
,
userStore
.
babyInfo
)
...
...
pages/shengzhangTestResult/shengzhangTestResult.vue
View file @
40699575
...
...
@@ -307,7 +307,7 @@
</
template
>
<
script
setup
>
import
{
ref
,
onMounted
}
from
'vue'
import
{
ref
,
onMounted
,
getCurrentInstance
}
from
'vue'
import
{
onLoad
,
onShareAppMessage
}
from
"@dcloudio/uni-app"
;
import
{
useShengzhangStore
}
from
'../../stores/shengzhangResult.js'
;
import
{
formatDate
,
jump
,
JumpType
}
from
'../../utils/index.js'
;
...
...
@@ -320,7 +320,8 @@ import md from '../../md';
const
isRecords
=
ref
(
false
);
const
shareText
=
ref
(
''
)
const
{
proxy
}
=
getCurrentInstance
();
const
$baseUrl
=
proxy
.
$baseUrl
;
onLoad
((
options
)
=>
{
isRecords
.
value
=
options
.
isRecords
;
// activeTab.value = isRecords.value ? 'history' : 'latest';
...
...
@@ -699,9 +700,9 @@ const backFailHandler = () => {
onShareAppMessage
(()
=>
{
return
{
title
:
shareText
.
value
,
title
:
shareText
.
value
||
"生长测评:精准评估宝宝发育水平"
,
path
:
`/pages/shengzhangTestResult/shengzhangTestResult`
,
imageUrl
:
''
imageUrl
:
$baseUrl
+
"share/shengzhang.png"
,
}
})
...
...
@@ -713,6 +714,15 @@ onMounted(async () => {
xcxPage
:
"测评结果页"
,
pageName
:
"测评结果页"
});
const
userStore
=
useUserStore
();
console
.
log
(
userStore
.
babyInfo
?.
content
?.
id
+
'--------------------'
,
shengzhangStore
?.
getGrowthCurveDataInfoHeight
?.
userDataPoints
)
if
(
!
userStore
.
babyInfo
?.
content
?.
id
||
!
shengzhangStore
?.
getGrowthCurveDataInfoHeight
?.
userDataPoints
){
jump
({
type
:
JumpType
.
INNER
,
url
:
"/pages/shengzhangTools/shengzhangTools"
})
return
;
}
//获取历史记录
const
historyListData
=
await
getGrowthHistoryList
();
...
...
@@ -761,7 +771,7 @@ onMounted(async () => {
}
}
const
userStore
=
useUserStore
();
const
babyId
=
userStore
.
babyInfo
?.
content
?.
id
;
const
babyDataHeight
=
{
...
...
pages/shengzhangTools/shengzhangTools.vue
View file @
40699575
...
...
@@ -802,6 +802,7 @@ const babyRefresh = async () => {
const
userStore
=
useUserStore
();
const
babyInfo
=
userStore
.
babyInfo
;
isNotLogin
.
value
=
false
;
isTip
.
value
=
false
if
(
userStore
?.
userInfo
?.
memberId
&&
userStore
?.
userInfo
?.
memberId
==
"not_login"
||
!
userStore
.
userInfo
...
...
@@ -809,7 +810,7 @@ const babyRefresh = async () => {
isNotLogin
.
value
=
true
;
}
console
.
log
(
babyInfo
?.
babyStage
+
'--------------------'
,
babyInfo
)
if
(
babyInfo
&&
babyInfo
.
babyStage
==
2
)
{
isTip
.
value
=
false
await
refreshBabyInfo
();
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment