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
5b57105a
Commit
5b57105a
authored
Jun 06, 2025
by
tao.huang
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
feat: 新增编辑宝宝
parent
eaf80157
Changes
5
Expand all
Show whitespace changes
Inline
Side-by-side
Showing
5 changed files
with
364 additions
and
110 deletions
+364
-110
MultiSelectLayer.vue
components/MultiSelectLayer.vue
+103
-0
RegisterLayer.vue
components/RegisterLayer.vue
+16
-9
person.vue
pages/person/person.vue
+196
-35
index.js
utils/index.js
+29
-0
My.vue
views/My.vue
+20
-66
No files found.
components/MultiSelectLayer.vue
0 → 100644
View file @
5b57105a
<
template
>
<Layer
:modelValue=
"modelValue"
:title=
"title"
:showCancel=
"true"
:showConfirm=
"true"
@
update:modelValue=
"$emit('update:modelValue', $event)"
@
confirm=
"onConfirm"
@
cancel=
"onCancel"
>
<template>
<view
class=
"multi-select-list"
>
<view
v-for=
"opt in options"
:key=
"opt"
class=
"multi-select-tag"
:class=
"
{ selected: selectedSet.has(opt) }"
@click="toggle(opt)"
>
<text>
{{
opt
}}
</text>
<image
v-if=
"selectedSet.has(opt)"
class=
"check-icon"
src=
"/static/check.png"
/>
</view>
</view>
</
template
>
</Layer>
</template>
<
script
setup
>
import
{
ref
,
watch
,
computed
}
from
"vue"
;
import
Layer
from
"./Layer.vue"
;
const
props
=
defineProps
({
modelValue
:
Boolean
,
title
:
String
,
options
:
{
type
:
Array
,
default
:
()
=>
[]
},
modelSelected
:
{
type
:
Array
,
default
:
()
=>
[]
},
max
:
Number
,
});
const
emit
=
defineEmits
([
"update:modelValue"
,
"update:selected"
,
"confirm"
,
"cancel"
]);
const
selected
=
ref
([...
props
.
modelSelected
]);
watch
(
()
=>
props
.
modelSelected
,
(
val
)
=>
(
selected
.
value
=
[...
val
])
);
const
selectedSet
=
computed
(()
=>
new
Set
(
selected
.
value
));
function
toggle
(
opt
)
{
if
(
selectedSet
.
value
.
has
(
opt
))
{
selected
.
value
=
selected
.
value
.
filter
((
v
)
=>
v
!==
opt
);
}
else
{
if
(
!
props
.
max
||
selected
.
value
.
length
<
props
.
max
)
{
selected
.
value
=
[...
selected
.
value
,
opt
];
}
}
emit
(
"update:selected"
,
selected
.
value
);
}
function
onConfirm
()
{
emit
(
"confirm"
,
selected
.
value
);
emit
(
"update:modelValue"
,
false
);
}
function
onCancel
()
{
emit
(
"cancel"
);
emit
(
"update:modelValue"
,
false
);
}
</
script
>
<
style
lang=
"less"
scoped
>
.multi-select-list {
display: flex;
flex-wrap: wrap;
gap: 24rpx 20rpx;
}
.multi-select-tag {
display: flex;
align-items: center;
padding: 0 32rpx;
height: 56rpx;
background: #fff;
border-radius: 28rpx;
color: #222;
font-size: 28rpx;
margin-bottom: 24rpx;
position: relative;
border: 1rpx solid #eee;
.check-icon {
width: 28rpx;
height: 28rpx;
margin-left: 8rpx;
}
&.selected {
background: #e9d3b1;
color: #b88a3a;
border: 1rpx solid #b88a3a;
}
}
</
style
>
\ No newline at end of file
components/RegisterLayer.vue
View file @
5b57105a
...
...
@@ -39,7 +39,7 @@
<PickerCustom
mode=
"selector"
:disabled=
"status == 0"
:range=
"genderOptions"
:range=
"genderOptions
.map(item => item.label)
"
:value=
"genderIndex"
:onPickerChange=
"onGenderChange"
:onLayerVisibleChange=
"onLayerVisibleChange"
...
...
@@ -64,7 +64,7 @@
<PickerCustom
mode=
"selector"
:disabled=
"status == 0"
:range=
"fetusOptions"
:range=
"fetusOptions
.map(item => item.label)
"
:value=
"fetusIndex"
:onPickerChange=
"onFetusChange"
:onLayerVisibleChange=
"onLayerVisibleChange"
...
...
@@ -203,8 +203,16 @@ const fetus = ref("");
// 0备孕 1孕中 2出生
const
status
=
ref
(
-
1
);
const
genderOptions
=
[
"男"
,
"女"
,
"未知"
];
const
fetusOptions
=
[
"一胎"
,
"二胎"
,
"三胎"
];
const
genderOptions
=
[
{
label
:
"男"
,
value
:
"M"
},
{
label
:
"女"
,
value
:
"F"
},
{
label
:
"未知"
,
value
:
"O"
}
];
const
fetusOptions
=
[
{
label
:
"一胎"
,
value
:
1
},
{
label
:
"二胎"
,
value
:
2
},
{
label
:
"三胎"
,
value
:
3
}
];
// date picker
const
dateValue
=
ref
([
50
,
0
,
0
]);
// 默认选中今年1月1日
...
...
@@ -215,17 +223,17 @@ function onDateChange(val) {
}
// gender picker
const
genderIndex
=
ref
(
0
);
const
genderDisplay
=
computed
(()
=>
gender
.
value
);
const
genderDisplay
=
computed
(()
=>
gender
.
value
?
genderOptions
[
genderIndex
.
value
].
label
:
""
);
function
onGenderChange
(
idx
)
{
genderIndex
.
value
=
idx
;
gender
.
value
=
genderOptions
[
idx
];
gender
.
value
=
genderOptions
[
idx
]
.
value
;
}
// fetus picker
const
fetusIndex
=
ref
(
0
);
const
fetusDisplay
=
computed
(()
=>
fetus
.
value
);
const
fetusDisplay
=
computed
(()
=>
fetus
.
value
?
fetusOptions
[
fetusIndex
.
value
].
label
:
""
);
function
onFetusChange
(
idx
)
{
fetusIndex
.
value
=
idx
;
fetus
.
value
=
fetusOptions
[
idx
];
fetus
.
value
=
fetusOptions
[
idx
]
.
value
;
}
function
onStatusChange
(
v
)
{
...
...
@@ -258,7 +266,6 @@ function handleBabyInfoConfirm() {
fetus
:
fetus
.
value
,
status
:
status
.
value
,
});
visible
.
value
=
false
;
}
function
openAgreement
()
{
// 跳转协议页面
...
...
pages/person/person.vue
View file @
5b57105a
This diff is collapsed.
Click to expand it.
utils/index.js
View file @
5b57105a
...
...
@@ -47,3 +47,32 @@ export function jump({ type, url, extra = {} }) {
console
.
error
(
'不支持的跳转类型'
)
}
}
/**
* 防连点函数
* @param {Function} fn 需要防连点的函数
* @param {number} [delay=1000] 防连点时间间隔(ms)
* @returns {Function} 包装后的防连点函数
*/
export
function
throttleTap
(
fn
,
delay
=
1000
)
{
let
timer
=
null
;
let
lastTime
=
0
;
return
function
(...
args
)
{
const
now
=
Date
.
now
();
if
(
now
-
lastTime
<
delay
)
{
// 小于间隔时间,阻止执行
console
.
log
(
'防连点'
)
return
;
}
lastTime
=
now
;
clearTimeout
(
timer
);
timer
=
setTimeout
(()
=>
{
fn
.
apply
(
this
,
args
);
},
delay
);
}
}
views/My.vue
View file @
5b57105a
...
...
@@ -33,7 +33,6 @@
<view
class=
"user-info"
:style=
"
{ 'min-height': cfgStatus.showDetail ? '343rpx' : '180rpx' }"
@click="handleRegister"
>
<view
class=
"user-header"
>
<view
class=
"avatar-container"
@
click=
"handleEditProfile"
>
...
...
@@ -127,15 +126,18 @@
</
template
>
<
script
setup
>
import
{
ref
,
onMounted
,
getCurrentInstance
}
from
"vue"
;
import
{
ref
,
onMounted
,
getCurrentInstance
,
computed
}
from
"vue"
;
import
RegisterLayer
from
"../components/RegisterLayer.vue"
;
import
BabySwitcher
from
"../components/BabySwitcher.vue"
;
import
WheelSelector
from
"../components/WheelSelector.vue"
;
import
{
WHEEL_OPTIONS_YL
,
WHEEL_OPTIONS_YZ
}
from
"@/cfg"
;
import
{
useUserStore
}
from
"@/stores/user"
;
import
{
throttleTap
}
from
"@/utils"
;
const
{
proxy
}
=
getCurrentInstance
();
const
$baseUrl
=
proxy
.
$baseUrl
;
const
userStore
=
useUserStore
();
const
cfgStatus
=
ref
({
openBabyCardDesc
:
false
,
showDetail
:
false
,
...
...
@@ -173,52 +175,7 @@ const toolList = ref([
},
]);
const
babyInfo
=
ref
({
babyName
:
"et"
,
babySkill
:
"occaecat"
,
babyAge
:
"2月龄"
,
babyAvatar
:
"sint ad sunt anim"
,
points
:
"23223"
,
babyStage
:
1
,
content
:
{
dueDate
:
"esse ea dolor id ipsum"
,
gestationalWeeks
:
"culpa"
,
babyType
:
"irure"
,
contentPreference
:
"occaecat commodo dolore"
,
followInfo
:
"est qui ea occaecat ad"
,
babyName
:
"Lorem"
,
babyBirthday
:
"est mollit do consectetur"
,
babyGender
:
"consectetur"
,
birthWeight
:
"dolore pariatur dolor"
,
birthHeight
:
"fugiat consectetur incididunt"
,
feedingType
:
"ipsum labore dolor in Lorem"
,
productPreference
:
"id voluptate"
,
purchaseChannel
:
"enim veniam in elit"
,
id
:
2212796.2919538617
,
memberBabyId
:
-
77291739.14081913
,
babyAvatar
:
"nisi Duis est"
,
backgroundImg
:
"laborum in esse ut deserunt"
,
},
allBabyBaseInfo
:
[
{
babyName
:
""
,
babyType
:
19188017.35935314
,
babyStage
:
"veniam Ut sunt cupidatat"
,
id
:
"officia pariatur proident"
,
typeName
:
"eu"
,
selected
:
false
,
},
{
babyName
:
""
,
babyType
:
34899428.44859558
,
babyStage
:
"incididunt"
,
id
:
"non"
,
typeName
:
"dolor irure id cupidatat"
,
selected
:
true
,
},
],
babyGender
:
"in voluptate ut"
,
});
const
babyInfo
=
computed
(()
=>
userStore
.
babyInfo
);
const
showRegisterLayer
=
ref
(
false
);
const
showBabySwitcher
=
ref
(
false
);
...
...
@@ -252,36 +209,33 @@ const navigateTo = (url) => {
// 编辑个人资料
const
handleEditProfile
=
()
=>
{
const
userStore
=
useUserStore
();
if
(
!
userStore
.
userInfo
||
JSON
.
stringify
(
userStore
.
userInfo
)
===
"{}"
)
{
return
;
}
navigateTo
(
"/pages/person/person"
);
navigateTo
(
`/pages/person/person?type=
${
userStore
.
babyInfo
?.
allBabyBaseInfo
?.
length
==
0
?
'add'
:
'edit'
}
`);
};
const
handleRegister
=
()
=>
{
// 判断是否已注册
if
(
!
cfgStatus
.
value
.
isRegister
)
{
// 调用登录接口
// console.log("phoneButton", phoneButton.value);
// phoneButton.value.triggerEvent("tap");
const onRegisterConfirm = throttleTap(async (data) => {
const reqData = {
id: userStore?.babyInfo?.id,
babyStage: data.status,
};
if (userStore?.babyInfo?.babyType != 0) {
reqData.babyGender = data.gender;
reqData.babyType = data.fetus;
}
return
;
};
console.log("reqData:", reqData);
const
onRegisterConfirm
=
async
(
data
)
=>
{
console
.
log
(
"onRegisterConfirm:"
,
data
);
showRegisterLayer.value = false;
const
userStore
=
useUserStore
();
await Promise.all[(userStore.loadUserInfo(), userStore.loadBabyInfo())];
initData();
};
}
, 5000)
;
// 获取用户信息
const initData = async () => {
const
userStore
=
useUserStore
();
if (!userStore.userInfo || JSON.stringify(userStore.userInfo) == "{}") {
cfgStatus.value.isRegister = false;
cfgStatus.value.showDetail = false;
...
...
@@ -306,7 +260,7 @@ const initData = async () => {
const getRealtimePhoneNumber = async (e) => {
console.log("获取手机号码", e);
const
userStore
=
useUserStore
();
if (e.detail.errMsg !== "getPhoneNumber:ok") {
uni.showToast({
title: "请授权使用手机号",
...
...
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