Commit 19462a4a authored by tao.huang's avatar tao.huang

feat: 我的注册

parent e6720212
export const PRIVACY_URL = "https://secret.feihe.com/secret.html";
export const MEMBER_URL = "https://secret.feihe.com/index.html";
export const WHEEL_OPTIONS_YL = [
{ label: "1月龄", desc: "宝宝开始对外界产生兴趣,会追视物体" },
{ label: "2月龄", desc: "能发出咿咿呀呀的声音,会对妈妈微笑" },
{ label: "3月龄", desc: "抬头能力增强,喜欢玩自己的小手" },
{ label: "4月龄", desc: "会翻身了,对周围事物充满好奇" },
{ label: "5月龄", desc: "手眼协调能力提升,喜欢抓取玩具" },
{ label: "6月龄", desc: "可以独自坐立,开始尝试固体食物" },
{ label: "7月龄", desc: "会爬行了,语言能力逐渐发展" },
{ label: "8月龄", desc: "能扶物站立,认知能力显著提升" },
{ label: "9月龄", desc: "开始学步,能说简单的词语" },
{ label: "10月龄", desc: "独立行走能力增强,喜欢模仿大人" },
{ label: "11月龄", desc: "语言理解能力提高,会简单互动" },
{ label: "12月龄", desc: "基本能独立行走,表达欲望增强" },
{ label: "13月龄", desc: "动作更加协调,喜欢探索新事物" },
{ label: "14月龄", desc: "语言表达更丰富,独立意识增强" },
{ label: "15月龄", desc: "手部精细动作发展,创造力萌芽" },
{ label: "16月龄", desc: "记忆力提升,开始学习分类概念" },
{ label: "17月龄", desc: "想象力丰富,喜欢角色扮演游戏" },
{ label: "18月龄", desc: "语言交流更流畅,社交能力发展" },
{ label: "19月龄", desc: "运动技能全面发展,好奇心旺盛" },
{ label: "20月龄", desc: "逻辑思维初步形成,会简单推理" },
{ label: "21月龄", desc: "情感表达更丰富,记忆力增强" },
{ label: "22月龄", desc: "独立性增强,生活技能提升" },
{ label: "23月龄", desc: "语言组织能力提高,喜欢提问" },
{ label: "24月龄", desc: "社交圈子扩大,懂得分享" },
{ label: "25月龄", desc: "创造性思维发展,喜欢音乐" },
{ label: "26月龄", desc: "注意力更集中,会完成简单任务" },
{ label: "27月龄", desc: "空间认知能力提升,喜欢拼图" },
{ label: "28月龄", desc: "语言表达更准确,理解能力增强" },
{ label: "29月龄", desc: "自我意识增强,情绪管理提升" },
{ label: "30月龄", desc: "逻辑思维更成熟,会简单计数" },
{ label: "31月龄", desc: "艺术创造力发展,喜欢绘画" },
{ label: "32月龄", desc: "记忆力显著提升,会讲简单故事" },
{ label: "33月龄", desc: "运动协调性好,喜欢户外活动" },
{ label: "34月龄", desc: "社交技能成熟,懂得合作" },
{ label: "35月龄", desc: "思维更加灵活,解决问题能力增强" },
{ label: "36月龄", desc: "全面发展,准备进入幼儿园阶段" },
];
export const WHEEL_OPTIONS_YZ = [
{ label: "孕1周", desc: "胚胎开始着床,激素水平发生变化,胚胎开始着床,激素水平发生变化,胚胎开始着床,激素水平发生变化,胚胎开始着床,激素水平发生变化,胚胎开始着床,激素水平发生变化,胚胎开始着床,激素水平发生变化" },
{ label: "孕2周", desc: "胎盘开始形成,为胎儿提供营养" },
{ label: "孕3周", desc: "胎儿心脏开始跳动,神经系统发育" },
{ label: "孕4周", desc: "胎儿大小如花生,开始形成四肢" },
{ label: "孕5周", desc: "胎儿面部开始发育,可见眼睛雏形" },
{ label: "孕6周", desc: "胎儿开始运动,脊椎继续发育" },
{ label: "孕7周", desc: "胎儿手指脚趾形成,大脑发育加快" },
{ label: "孕8周", desc: "胎儿所有器官雏形完成,开始生长" },
{ label: "孕9周", desc: "胎儿开始吞咽羊水,肌肉发育" },
{ label: "孕10周", desc: "胎儿指甲开始生长,性别特征显现" },
{ label: "孕11周", desc: "胎儿可以做出简单动作,头部变圆" },
{ label: "孕12周", desc: "胎儿开始产生尿液,骨骼继续钙化" },
{ label: "孕13周", desc: "胎儿vocal cords形成,可发声" },
{ label: "孕14周", desc: "胎儿开始产生胎动,母体可感知" },
{ label: "孕15周", desc: "胎儿皮下脂肪开始形成,体型增大" },
{ label: "孕16周", desc: "胎儿听力开始发育,对声音敏感" },
{ label: "孕17周", desc: "胎儿免疫系统开始发育,产生抗体" },
{ label: "孕18周", desc: "胎儿睡眠周期形成,活动规律" },
{ label: "孕19周", desc: "胎儿肺部发育,为呼吸做准备" },
{ label: "孕20周", desc: "胎儿听力继续发育,对外界声音反应" },
{ label: "孕21周", desc: "胎儿眉毛睫毛生长,面部特征明显" },
{ label: "孕22周", desc: "胎儿皮肤变厚,开始长出胎毛" },
{ label: "孕23周", desc: "胎儿体重快速增长,运动更频繁" },
{ label: "孕24周", desc: "胎儿肺部继续发育,产生肺表面活性物质" },
{ label: "孕25周", desc: "胎儿脂肪积累加快,体型继续增大" },
{ label: "孕26周", desc: "胎儿眼睛可以睁开,对光有反应" },
{ label: "孕27周", desc: "胎儿大脑快速发育,神经系统成熟" },
{ label: "孕28周", desc: "胎儿各器官功能逐渐完善" },
{ label: "孕29周", desc: "胎儿骨骼继续钙化,头部下降" },
{ label: "孕30周", desc: "胎儿体重持续增加,活动空间减少" },
{ label: "孕31周", desc: "胎儿消化系统发育成熟,可消化羊水" },
{ label: "孕32周", desc: "胎儿皮下脂肪继续积累,体温调节能力增强" },
{ label: "孕33周", desc: "胎儿免疫系统继续发育,获得母体抗体" },
{ label: "孕34周", desc: "胎儿肺部发育接近成熟,准备独立呼吸" },
{ label: "孕35周", desc: "胎儿体重快速增加,为出生做准备" },
{ label: "孕36周", desc: "胎儿头部继续下降,为分娩做准备" },
{ label: "孕37周", desc: "胎儿各器官发育完善,可以安全出生" },
{ label: "孕38周", desc: "胎儿继续增重,准备出生" },
{ label: "孕39周", desc: "胎儿位置固定,随时可能出生" },
{ label: "孕40周", desc: "胎儿发育完全成熟,即将出生" },
];
<template>
<view class="baby-switcher-container">
<view class="baby-switcher-mask" @click.self="onClose"> </view>
<view class="baby-switcher-popup">
<view
v-for="baby in babyList"
:key="baby.id"
class="baby-item"
@click="selectBaby(baby)"
>
<text>{{ baby.babyName || "暂无昵称" }}</text>
<view
class="selected-icon"
:style="{ backgroundColor: baby.selected ? '#d3a358' : '#E8E8E8' }"
/>
</view>
<view v-if="babyList.length < 3" class="baby-item add-item" @click="onAdd">
<image :src="addIcon" class="add-icon" />
</view>
</view>
</view>
</template>
<script setup>
import { defineProps, defineEmits } from "vue";
const props = defineProps({
show: Boolean,
babyList: {
type: Array,
default: () => [],
},
addIcon: {
type: String,
default: "", // 传入新增icon路径
},
});
const emits = defineEmits(["close", "select", "add"]);
function onClose() {
emits("close");
}
function selectBaby(baby) {
emits("select", baby);
}
function onAdd() {
emits("add");
}
</script>
<style lang="less" scoped>
.baby-switcher-container {
touch-action: none;
}
.baby-switcher-mask {
position: fixed;
left: 0;
top: 0;
right: 0;
bottom: 0;
z-index: 1;
}
.baby-switcher-popup {
position: absolute;
left: 0;
top: 40rpx;
z-index: 2;
background: #fff;
border-radius: 16rpx;
padding: 10rpx 36rpx 22rpx 36rpx;
box-shadow: 0 0 30rpx rgba(204, 204, 204, 0.8);
box-sizing: border-box;
min-width: 247rpx;
}
.baby-item {
display: flex;
align-items: center;
justify-content: center;
padding: 20rpx 25rpx;
font-size: 26rpx;
font-weight: 500;
color: #1d1e25;
flex-wrap: nowrap;
border-bottom: 1px solid #eee;
&:nth-child(3) {
border-bottom: none;
}
}
.selected-icon {
width: 12rpx;
height: 12rpx;
margin-left: 17rpx;
background-color: #e8e8e8;
border-radius: 50%;
}
.add-item {
margin-top: 10rpx;
padding-top: 20rpx;
padding: 10rpx 0;
border-bottom: none;
}
.add-icon {
width: 96rpx;
height: 36rpx;
display: block;
}
</style>
\ No newline at end of file
......@@ -27,24 +27,40 @@
>
<template v-if="mode === 'date'">
<picker-view-column>
<view v-for="(item, idx) in years" :key="idx" class="picker-layer-item">
<view
v-for="(item, idx) in years"
:key="idx"
class="picker-layer-item"
>
{{ item }}
</view>
</picker-view-column>
<picker-view-column>
<view v-for="(item, idx) in months" :key="idx" class="picker-layer-item">
<view
v-for="(item, idx) in months"
:key="idx"
class="picker-layer-item"
>
{{ item }}
</view>
</picker-view-column>
<picker-view-column>
<view v-for="(item, idx) in days" :key="idx" class="picker-layer-item">
{{ item === '请选择' ? item : `${item}日` }}
<view
v-for="(item, idx) in days"
:key="idx"
class="picker-layer-item"
>
{{ item === "请选择" ? item : `${item}日` }}
</view>
</picker-view-column>
</template>
<template v-else>
<picker-view-column v-for="(col, colIdx) in columns" :key="colIdx">
<view v-for="(item, idx) in col" :key="idx" class="picker-layer-item">
<view
v-for="(item, idx) in col"
:key="idx"
class="picker-layer-item"
>
{{ item }}
</view>
</picker-view-column>
......@@ -60,7 +76,7 @@ import { ref, computed, watch } from "vue";
const props = defineProps({
mode: {
type: String,
default: 'custom', // 'date' | 'custom'
default: "custom", // 'date' | 'custom'
},
range: {
type: Array,
......@@ -78,33 +94,80 @@ const props = defineProps({
type: Function,
default: () => {},
},
onStatusChange: {
type: Function,
default: () => {},
},
disabled: {
type: Boolean,
default: false,
},
});
const show = ref(false);
// date模式相关
const currentYear = new Date().getFullYear();
const today = new Date();
const currentYear = today.getFullYear();
const currentMonth = today.getMonth() + 1;
const currentDay = today.getDate();
// 计算未来280天的日期
const futureDate = new Date();
futureDate.setDate(futureDate.getDate() + 280);
const futureYear = futureDate.getFullYear();
const futureMonth = futureDate.getMonth() + 1;
const futureDay = futureDate.getDate();
const years = computed(() => {
const arr = [];
for (let i = 1970; i <= currentYear; i++) {
const startYear = currentYear - 3;
const endYear = futureYear;
for (let i = startYear; i <= endYear; i++) {
arr.push(i);
}
return arr;
});
const months = computed(() => {
const [yearIdx] = pickerValue.value;
const selectedYear = years.value[yearIdx];
const arr = [];
for (let i = 1; i <= 12; i++) {
let startMonth = 1;
let endMonth = 12;
if (selectedYear === currentYear - 3) {
startMonth = currentMonth;
}
if (selectedYear === futureYear) {
endMonth = futureMonth;
}
for (let i = startMonth; i <= endMonth; i++) {
arr.push(i);
}
return arr;
});
const days = computed(() => {
const [yearIdx, monthIdx] = pickerValue.value;
const year = years.value[yearIdx] || years.value[0];
const month = months.value[monthIdx] || months.value[0];
const dayCount = new Date(year, month, 0).getDate();
const arr = ['请选择'];
for (let i = 1; i <= dayCount; i++) {
const selectedYear = years.value[yearIdx];
const selectedMonth = months.value[monthIdx];
const dayCount = new Date(selectedYear, selectedMonth, 0).getDate();
const arr = ["请选择"];
let startDay = 1;
let endDay = dayCount;
if (selectedYear === currentYear - 3 && selectedMonth === currentMonth) {
startDay = currentDay;
}
if (selectedYear === futureYear && selectedMonth === futureMonth) {
endDay = futureDay;
}
for (let i = startDay; i <= endDay; i++) {
arr.push(i);
}
return arr;
......@@ -120,7 +183,7 @@ const columns = computed(() => {
});
const defaultValue = computed(() => {
if (props.mode === 'date') {
if (props.mode === "date") {
// 默认选中今年1月1日
return [years.value.length - 1, 0, 0];
} else if (Array.isArray(props.value)) {
......@@ -135,7 +198,7 @@ const pickerValue = ref([...defaultValue.value]);
watch(
() => props.value,
(val) => {
if (props.mode === 'date') {
if (props.mode === "date") {
pickerValue.value = [...val];
} else if (Array.isArray(val)) {
pickerValue.value = [...val];
......@@ -146,7 +209,9 @@ watch(
);
function open() {
if (props.disabled) return;
pickerValue.value = [...defaultValue.value];
show.value = true;
props.onLayerVisibleChange(true);
}
......@@ -156,19 +221,35 @@ function close() {
}
function confirm() {
close();
if (props.mode === 'date') {
if (props.mode === "date") {
const [yIdx, mIdx, dIdx] = pickerValue.value;
if(dIdx === 0) {
props.onPickerChange('');
if (dIdx === 0) {
props.onPickerChange("");
return;
}
const year = years.value[yIdx];
const month = months.value[mIdx];
const day = days.value[dIdx];
const dateStr = `${year}-${String(month).padStart(2, '0')}-${String(day).padStart(2, '0')}`;
const dateStr = `${year}-${String(month).padStart(2, "0")}-${String(
day
).padStart(2, "0")}`;
props.onPickerChange(dateStr);
// 新增:判断状态并回调
const today = new Date();
const selectedDate = new Date(year, month - 1, day);
// 清除时分秒
today.setHours(0, 0, 0, 0);
selectedDate.setHours(0, 0, 0, 0);
let status = -1;
if (selectedDate.getTime() <= today.getTime()) {
status = 2;
} else {
status = 1;
}
props.onStatusChange(status);
} else {
// 单列时只返回索引,否则返回数组
if (columns.value.length === 1) {
......@@ -180,7 +261,7 @@ function confirm() {
}
function onChange(e) {
let val = e.detail.value;
if (props.mode === 'date') {
if (props.mode === "date") {
// 如果天数溢出,自动修正到最大天数
const maxDay = days.value.length;
if (val[2] >= maxDay) val[2] = maxDay - 1;
......@@ -308,4 +389,8 @@ function onChange(e) {
pointer-events: none;
}
.picker-custom[disabled] {
opacity: 0.5;
pointer-events: none;
}
</style>
\ No newline at end of file
......@@ -2,6 +2,7 @@
<Layer
v-model="visible"
:customHeader="true"
:maskClosable="false"
@confirm="handleConfirm"
@cancel="handleCancel"
>
......@@ -13,16 +14,22 @@
<PickerCustom
mode="date"
:value="dateValue"
:disabled="status == 0"
:onPickerChange="onDateChange"
:onLayerVisibleChange="onLayerVisibleChange"
:onStatusChange="onStatusChange"
>
<view class="register-baby-info-picker">
<view
class="register-baby-info-picker"
:style="status == 0 ? 'background: #e9edf1;' : ''"
>
<view
class="register-baby-info-picker-value"
:style="dateDisplay ? 'color: #1d1e25;' : ''"
>{{ dateDisplay || "请选择宝宝的生日或预产期" }}</view
>
<image
v-if="status != 0"
class="register-baby-info-picker-arrow"
:src="$baseUrl + 'registerLayer/icon_arrow_yellow.png'"
mode="aspectFit"
......@@ -31,18 +38,23 @@
</PickerCustom>
<PickerCustom
mode="selector"
:disabled="status == 0"
:range="genderOptions"
:value="genderIndex"
:onPickerChange="onGenderChange"
:onLayerVisibleChange="onLayerVisibleChange"
>
<view class="register-baby-info-picker">
<view
class="register-baby-info-picker"
:style="status == 0 ? 'background: #e9edf1;' : ''"
>
<view
class="register-baby-info-picker-value"
:style="genderDisplay ? 'color: #1d1e25;' : ''"
>{{ genderDisplay || "请选择宝宝的性别" }}</view
>
<image
v-if="status != 0"
class="register-baby-info-picker-arrow"
:src="$baseUrl + 'registerLayer/icon_arrow_yellow.png'"
mode="aspectFit"
......@@ -51,24 +63,50 @@
</PickerCustom>
<PickerCustom
mode="selector"
:disabled="status == 0"
:range="fetusOptions"
:value="fetusIndex"
:onPickerChange="onFetusChange"
:onLayerVisibleChange="onLayerVisibleChange"
>
<view class="register-baby-info-picker">
<view
class="register-baby-info-picker"
:style="status == 0 ? 'background: #e9edf1;' : ''"
>
<view
class="register-baby-info-picker-value"
:style="fetusDisplay ? 'color: #1d1e25;' : ''"
>{{ fetusDisplay || "请选择胎数" }}</view
>
<image
v-if="status != 0"
class="register-baby-info-picker-arrow"
:src="$baseUrl + 'registerLayer/icon_arrow_yellow.png'"
mode="aspectFit"
/>
</view>
</PickerCustom>
<view class="register-baby-info-status">
<view
class="register-baby-info-status-item"
:class="{ active: status === 0 }"
@click="toggleStatus(0)"
>
<view class="register-baby-info-status-item-icon">
<image
:src="
$baseUrl +
(status === 0
? 'registerLayer/circle_yes.png'
: 'registerLayer/circle_no.png')
"
mode="aspectFit"
/>
</view>
<view class="register-baby-info-status-item-text">备孕中</view>
</view>
</view>
<view class="register-baby-info-agreement">
<image
class="register-baby-info-agreement-icon"
......@@ -109,13 +147,16 @@
@click="checked.option2 = !checked.option2"
/>
</view>
<view class="register-baby-info-btn" @click="handleBabyInfoConfirm">
<view
class="register-baby-info-btn"
:style="isBtnActive ? 'background: #d3a358;' : 'background: #e9edf1;'"
@click="handleBabyInfoConfirm"
>
完成
</view>
</view>
</Layer>
</template>
<script setup>
import { ref, watch, computed } from "vue";
import Layer from "./Layer.vue";
......@@ -132,7 +173,6 @@ const emit = defineEmits([
]);
const visible = ref(props.modelValue);
const imageUrl = ref(props.value);
watch(
() => props.modelValue,
......@@ -142,17 +182,8 @@ watch(
() => visible.value,
(val) => emit("update:modelValue", val)
);
watch(
() => props.value,
(val) => (imageUrl.value = val)
);
function removeImage() {
imageUrl.value = "";
emit("update:value", "");
}
function handleConfirm() {
emit("confirm", imageUrl.value);
visible.value = false;
}
function handleCancel() {
......@@ -169,9 +200,11 @@ const checked = ref({
const date = ref("");
const gender = ref("");
const fetus = ref("");
// 0备孕 1孕中 2出生
const status = ref(-1);
const genderOptions = ["男", "女", "保密"];
const fetusOptions = ["单胎", "多胎"];
const genderOptions = ["男", "女", "未知"];
const fetusOptions = ["一胎", "二胎", "三胎"];
// date picker
const dateValue = ref([50, 0, 0]); // 默认选中今年1月1日
......@@ -194,48 +227,36 @@ function onFetusChange(idx) {
fetusIndex.value = idx;
fetus.value = fetusOptions[idx];
}
function onLayerVisibleChange() {}
function handleBabyInfoConfirm() {
if (!checked.value.option1 || !checked.value.option2) {
uni.showToast({
title: "请先阅读并同意协议",
icon: "none",
});
return;
}
console.log(date.value, gender.value, fetus.value);
function onStatusChange(v) {
status.value = v;
}
if(!date.value) {
uni.showToast({
title: "请选择宝宝的生日或预产期",
icon: "none",
});
return;
}
function onLayerVisibleChange() {}
if(!gender.value) {
uni.showToast({
title: "请选择宝宝的性别",
icon: "none",
});
return;
const isBtnActive = computed(() => {
if (status.value === 0) {
return checked.value.option1 && checked.value.option2;
} else {
return (
checked.value.option1 &&
checked.value.option2 &&
!!date.value &&
!!gender.value &&
!!fetus.value
);
}
});
if(!fetus.value) {
uni.showToast({
title: "请选择胎数",
icon: "none",
});
function handleBabyInfoConfirm() {
if (!isBtnActive.value) {
return;
}
emit("confirm", {
date: date.value,
gender: gender.value,
fetus: fetus.value,
status: status.value,
});
visible.value = false;
}
......@@ -243,6 +264,22 @@ function openAgreement() {
// 跳转协议页面
uni.navigateTo({ url: "/pages/agreement/index" });
}
function toggleStatus(val) {
if (status.value === val) {
status.value = -1; // 取消高亮
} else {
status.value = val; // 选中
if (val === 0) {
date.value = "";
dateDisplay.value = "";
gender.value = "";
genderIndex.value = 0;
fetus.value = "";
fetusIndex.value = 0;
}
}
}
</script>
<style lang="less" scoped>
......@@ -273,7 +310,7 @@ function openAgreement() {
.register-baby-info-picker {
width: 654rpx;
background: #fff;
border-radius: 24rpx;
border-radius: 44rpx;
margin-bottom: 28rpx;
padding: 0 32rpx;
height: 94rpx;
......@@ -282,10 +319,49 @@ function openAgreement() {
align-items: center;
box-shadow: 0 4rpx 24rpx 0 rgba(211, 163, 88, 0.04);
border: none;
margin-left: auto;
margin-right: auto;
position: relative;
}
.register-baby-info-status {
width: 654rpx;
margin-bottom: 28rpx;
display: flex;
justify-content: center;
}
.register-baby-info-status-item {
display: flex;
align-items: center;
justify-content: center;
width: 100%;
height: 94rpx;
background: #fff;
color: #bdbfc3;
border-radius: 44rpx;
cursor: pointer;
transition: background 0.2s, color 0.2s;
box-sizing: border-box;
.register-baby-info-status-item-icon {
width: 32rpx;
height: 32rpx;
image {
width: 100%;
height: 100%;
display: block;
}
}
.register-baby-info-status-item-text {
font-size: 32rpx;
color: #bdbfc3;
margin-left: 12rpx;
transition: color 0.2s;
}
}
.register-baby-info-status-item.active {
border: 2rpx solid #d3a358;
color: #d3a358;
.register-baby-info-status-item-text {
color: #d3a358;
}
}
.register-baby-info-picker-value {
font-size: 32rpx;
color: #bdbfc3;
......@@ -366,4 +442,5 @@ function openAgreement() {
align-items: center;
justify-content: center;
}
</style>
\ No newline at end of file
</style>
<template>
<view class="wheel-selector">
<image class="wheel-bg" :src="bgImg" mode="aspectFit" />
<view
class="wheel-options"
@touchstart="onTouchStart"
@touchmove.prevent="onTouchMove"
@touchend="onTouchEnd"
>
<view
v-for="opt in visibleOptions"
:key="opt.idx + '-' + opt.pos"
class="wheel-option"
:class="{ selected: opt.pos === 0 }"
:style="getOptionStyle(opt)"
>
<image
class="wheel-icon"
:class="{ 'wheel-icon-selected': opt.pos === 0 }"
:src="opt.pos === 0 ? iconSelected : iconNormal"
mode="aspectFit"
/>
<text class="wheel-label">{{ opt.item.label }}</text>
</view>
</view>
</view>
</template>
<script setup>
import { ref, watch, computed } from "vue";
const props = defineProps({
options: { type: Array, required: true }, // [{label: '七月龄'}, ...]
selectedIndex: { type: Number, default: 0 },
bgImg: { type: String, required: true },
iconNormal: { type: String, required: true },
iconSelected: { type: String, required: true },
});
const emits = defineEmits(["update:selectedIndex", "change"]);
const currentIndex = ref(props.selectedIndex);
// 计算最多展示三个 option
const visibleOptions = computed(() => {
const total = props.options.length;
const arr = [];
for (let i = 0; i < 3; i++) {
if (currentIndex.value + i < total) {
arr.push({
item: props.options[currentIndex.value + i],
idx: currentIndex.value + i,
pos: i,
});
}
}
return arr;
});
watch(
() => props.selectedIndex,
(val) => {
currentIndex.value = val;
}
);
let startY = 0;
function onTouchStart(e) {
startY = e.touches[0].clientY;
}
function onTouchMove(e) {
const deltaY = e.touches[0].clientY - startY;
if (Math.abs(deltaY) > 30) {
// 滑动阈值
if (deltaY > 0 && currentIndex.value > 0) {
currentIndex.value -= 1;
startY = e.touches[0].clientY;
} else if (
deltaY < 0 &&
currentIndex.value < props.options.length - 1
) {
currentIndex.value += 1;
startY = e.touches[0].clientY;
}
emits("update:selectedIndex", currentIndex.value);
emits("change", currentIndex.value);
}
}
function onTouchEnd() {
// nothing
}
function getOptionStyle(opt) {
const positions = [
{ x: 34, y: 94 },
{ x: 118, y: 278 },
{ x: 50, y: 446 },
];
const pos = positions[opt.pos] || positions[positions.length - 1];
const _oo = {
position: "absolute",
left: `${pos.x}rpx`,
top: `${pos.y}rpx`,
opacity: 1,
zIndex: 10 - opt.pos,
}
return _oo;
}
</script>
<style scoped lang="less">
.wheel-selector {
position: absolute;
top: 128rpx;
left: 0;
width: 340rpx;
height: 540rpx;
}
.wheel-bg {
position: absolute;
left: 0;
top: 94rpx;
width: 143rpx;
height: 436rpx;
z-index: 0;
display: block;
}
.wheel-options {
position: absolute;
left: 0;
top: 0;
width: 100%;
height: 100%;
z-index: 1;
display: flex;
flex-direction: column;
align-items: flex-start;
justify-content: center;
pointer-events: auto;
touch-action: none;
}
.wheel-option {
position: absolute;
width: 220rpx;
height: 60rpx;
display: flex;
align-items: center;
transition: all 0.7s, opacity 0.2s;
.wheel-icon {
width: 24rpx;
height: 24rpx;
display: block;
}
.wheel-icon-selected {
width: 56rpx;
height: 56rpx;
display: block;
}
.wheel-label {
font-size: 28rpx;
color: #FFFFFF;
text-shadow: 0 2rpx 8rpx #333333;
font-weight: bold;
}
}
</style>
\ No newline at end of file
......@@ -91,6 +91,7 @@
:value="getPickerIndex(item)"
:onPickerChange="(e) => onPickerChange(e, item.name)"
:onLayerVisibleChange="(e) => (pageStatus.btnStatus = !e)"
:onStatusChange="onDateStatusChange"
>
<view class="form-input-box">
<view class="form-input">{{
......@@ -373,6 +374,12 @@ watch(
}
}
);
function onDateStatusChange(status) {
if (status === '已出生' || status === '孕中') {
formData.value.currentBaby = status;
}
}
</script>
<style lang="less" scoped>
......
import { defineStore } from "pinia";
import {
defineStore
} from 'pinia';
import {
autoLoginByCode,
fetchUserInfo,
fetchBabyInfo,
fetchAutoPhone
} from '../api/user.js';
import {
useGlobalStore
} from './global.js';
autoLoginByCode,
fetchUserInfo,
fetchBabyInfo,
fetchAutoPhone,
} from "../api/user.js";
import { useGlobalStore } from "./global.js";
const globalStore = useGlobalStore();
export const useUserStore = defineStore('userInfo', {
state: () => {
return {
userInfo: null,
babyInfo: null,
};
},
actions: {
/**
* 更新用户信息
* @param {Object} userInfo
*/
setUserInfo(userInfo) {
this.userInfo = userInfo;
},
/**
* 更新宝宝信息
* @param {Object} babyInfo
*/
setBabyInfo(babyInfo) {
this.babyInfo = babyInfo;
},
export const useUserStore = defineStore("userInfo", {
state: () => {
return {
userInfo: {
// memberId: "12",
// memberName: "hzt",
},
babyInfo: null,
};
},
actions: {
/**
* 更新用户信息
* @param {Object} userInfo
*/
setUserInfo(userInfo) {
this.userInfo = userInfo;
},
/**
* 用户手机号验证的回调方法,用于获取encryptedData、iv、code,然后调用fetchAutoPhone接口完成手机号授权
* @param {Object} data : {encryptedData, iv, code}
* @returns
*/
async phoneCallback(data) {
uni.login({
provider: 'weixin',
success: async (res) => {
// console.log('wxAutoLogin', res);
if (res.errMsg === 'login:ok') {
// 用户手机授权
await fetchAutoPhone({
phoneEncryptedData: data.encryptedData,
phoneIv: data.iv,
code: data.code,
codeLogin: res.code
});
// 授权注册成功后做一次登录
this.wxAutoLogin();
} else {
uni.showToast({
title: res.errMsg,
icon: 'error'
});
}
},
});
/**
* 更新宝宝信息
* @param {Object} babyInfo
*/
setBabyInfo(babyInfo) {
this.babyInfo = babyInfo;
},
},
/**
* 用户手机号验证的回调方法,用于获取encryptedData、iv、code,然后调用fetchAutoPhone接口完成手机号授权
* @param {Object} data : {encryptedData, iv, code}
* @returns
*/
async phoneCallback(data) {
uni.login({
provider: "weixin",
success: async (res) => {
// console.log('wxAutoLogin', res);
if (res.errMsg === "login:ok") {
// 用户手机授权
await fetchAutoPhone({
phoneEncryptedData: data.encryptedData,
phoneIv: data.iv,
code: data.code,
codeLogin: res.code,
});
// 授权注册成功后做一次登录
this.wxAutoLogin();
} else {
uni.showToast({
title: res.errMsg,
icon: "error",
});
}
},
});
},
/**
* 获取用户信息
*/
async loadUserInfo() {
const {
data
} = await fetchUserInfo();
console.log('userInfo', data);
if (data?.memberId !== 'not_login') {
this.userInfo = data;
}
},
/**
* 获取用户信息
*/
async loadUserInfo() {
const { data } = await fetchUserInfo();
console.log("userInfo", data);
if (data?.memberId !== "not_login") {
this.userInfo = data;
}
},
/**
* 获取宝宝信息
*/
async loadBabyInfo() {
const {
data
} = await fetchBabyInfo();
console.log('babyInfo', data);
if (data?.memberId !== 'not_login') {
this.babyInfo = data;
}
},
/**
* 获取宝宝信息
*/
async loadBabyInfo() {
const { data } = await fetchBabyInfo();
console.log("babyInfo", data);
if (data?.memberId !== "not_login") {
this.babyInfo = data;
}
},
/**
* wx.login 获取code后,调用此方法完成登录
* @param {String} code
*/
async autoLoginByCode(code) {
const {
data
} = await autoLoginByCode(code);
console.log('autoLoginByCode', data);
// 如果登录成功,获取用户信息和宝宝信息,更新到state中,方便全局使用
if (data && data.cuk) {
globalStore.setCuk(data.cuk);
/**
* wx.login 获取code后,调用此方法完成登录
* @param {String} code
*/
async autoLoginByCode(code) {
const { data } = await autoLoginByCode(code);
console.log("autoLoginByCode", data);
// 如果登录成功,获取用户信息和宝宝信息,更新到state中,方便全局使用
if (data && data.cuk) {
globalStore.setCuk(data.cuk);
this.loadUserInfo();
this.loadBabyInfo();
}
},
this.loadUserInfo();
this.loadBabyInfo();
}
},
/**
* 用户自动登录
*/
async wxAutoLogin() {
uni.login({
provider: 'weixin',
success: (res) => {
console.log('wxAutoLogin', res);
if (res.errMsg === 'login:ok') {
this.autoLoginByCode(res.code);
} else {
uni.showToast({
title: res.errMsg,
icon: 'error'
});
}
},
});
},
},
});
\ No newline at end of file
/**
* 用户自动登录
*/
async wxAutoLogin() {
uni.login({
provider: "weixin",
success: (res) => {
console.log("wxAutoLogin", res);
if (res.errMsg === "login:ok") {
this.autoLoginByCode(res.code);
} else {
uni.showToast({
title: res.errMsg,
icon: "error",
});
}
},
});
},
},
});
This diff is collapsed.
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