Commit 72625f61 authored by tao.huang's avatar tao.huang

feat: form

parent 3ef04c4e
......@@ -17,7 +17,7 @@
<view class="picker-layer-view-mask-top"></view>
<view class="picker-layer-view-mask-bottom"></view>
<!-- 半屏picker-view -->
<!-- 多列picker-view -->
<picker-view
class="picker-layer-view"
mask-style="background: rgb(246, 248, 250); z-index: 0;"
......@@ -25,29 +25,49 @@
:value="pickerValue"
@change="onChange"
>
<picker-view-column>
<view
v-for="(item, idx) in range"
:key="idx"
class="picker-layer-item"
>
{{ item }}
</view>
</picker-view-column>
<template v-if="mode === 'date'">
<picker-view-column>
<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">
{{ item }}
</view>
</picker-view-column>
<picker-view-column>
<view v-for="(item, idx) in days" :key="idx" class="picker-layer-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">
{{ item }}
</view>
</picker-view-column>
</template>
</picker-view>
</view>
</view>
</view>
</template>
<script setup>
import { ref } from "vue";
import { ref, computed, watch } from "vue";
const props = defineProps({
mode: {
type: String,
default: 'custom', // 'date' | 'custom'
},
range: {
type: Array,
default: () => [],
},
value: {
type: [Number, Array],
default: 0,
},
onPickerChange: {
......@@ -62,12 +82,72 @@ const props = defineProps({
const show = ref(false);
const pickerValue = ref(props.value);
// date模式相关
const currentYear = new Date().getFullYear();
const years = computed(() => {
const arr = [];
for (let i = 1970; i <= currentYear; i++) {
arr.push(i);
}
return arr;
});
const months = computed(() => {
const arr = [];
for (let i = 1; i <= 12; 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++) {
arr.push(i);
}
return arr;
});
// custom模式相关
const columns = computed(() => {
if (Array.isArray(props.range[0])) {
return props.range;
} else {
return [props.range];
}
});
const defaultValue = computed(() => {
if (props.mode === 'date') {
// 默认选中今年1月1日
return [years.value.length - 1, 0, 0];
} else if (Array.isArray(props.value)) {
return props.value;
} else {
return [props.value];
}
});
const pickerValue = ref([...defaultValue.value]);
watch(
() => props.value,
(val) => {
if (props.mode === 'date') {
pickerValue.value = [...val];
} else if (Array.isArray(val)) {
pickerValue.value = [...val];
} else {
pickerValue.value = [val];
}
}
);
function open() {
pickerValue.value = props.value;
pickerValue.value = [...defaultValue.value];
show.value = true;
props.onLayerVisibleChange(true);
}
function close() {
......@@ -75,13 +155,33 @@ function close() {
props.onLayerVisibleChange(false);
}
function confirm() {
/* 处理选中逻辑 */ close();
props.onPickerChange(pickerValue.value);
close();
if (props.mode === 'date') {
const [yIdx, mIdx, dIdx] = pickerValue.value;
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')}`;
props.onPickerChange(dateStr);
} else {
// 单列时只返回索引,否则返回数组
if (columns.value.length === 1) {
props.onPickerChange(pickerValue.value[0]);
} else {
props.onPickerChange([...pickerValue.value]);
}
}
}
function onChange(e) {
console.log("onPcikChange", e);
pickerValue.value = e.detail.value;
let val = e.detail.value;
if (props.mode === 'date') {
// 如果天数溢出,自动修正到最大天数
const maxDay = days.value.length;
if (val[2] >= maxDay) val[2] = maxDay - 1;
pickerValue.value = val;
} else {
pickerValue.value = val;
}
}
</script>
<style lang="less" scoped>
......
......@@ -51,17 +51,22 @@
<form @submit="onSubmit">
<view class="person-info">
<block
v-for="(item, index) in formItems.slice(
0,
pageStatus.formStatus == 1 ? formItems.length : 6
)"
v-for="(item, index) in formItems
.filter(formItemFilter)
.slice(
0,
formData.currentBaby == '已出生' && pageStatus.formStatus == 2
? 6
: formItems.length
)"
:key="item.name"
>
<view
class="form-row"
:style="{
'border-bottom':
pageStatus.formStatus == 0 && index == formItems.length - 1
pageStatus.formStatus == 0 &&
index == formItems.filter(formItemFilter).length - 1
? 'none'
: '1rpx solid #f2f2f2',
}"
......@@ -81,6 +86,7 @@
<!-- 选择器类型 -->
<PickerCustom
v-else-if="item.type === 'picker'"
:mode="item.mode"
:range="item.range"
:value="getPickerIndex(item)"
:onPickerChange="(e) => onPickerChange(e, item.name)"
......@@ -141,23 +147,23 @@
<view class="form-bottom"></view>
<button v-if="pageStatus.btnStatus" form-type="submit" class="form-btn">
提交
保存
</button>
</form>
</view>
</template>
<script setup>
import { ref } from "vue";
import { ref, watch } from "vue";
import PickerCustom from "../../components/PickerCustom.vue";
const pageStatus = ref({
formStatus: 2, // 0: 隐藏 1: 展开, 2: 收起
formStatus: 0, // 0: 隐藏 1: 展开, 2: 收起
btnStatus: true, // 是否显示提交按钮
});
const formData = ref({
currentBaby: "",
currentBaby: "备孕",
nickName: "",
dateOfBirth: "",
gender: "",
......@@ -167,9 +173,37 @@ const formData = ref({
productLike: "",
specialAttention: "",
channel: "",
avatarUrl: ""
avatarUrl: "",
});
const FormMap = {
备孕: ["currentBaby", "dateOfBirth", "specialAttention"],
孕中: [
"currentBaby",
"dateOfBirth2",
"yz",
"babyIndex",
"contentLike",
"specialAttention",
],
已出生: [
"currentBaby",
"nickName",
"dateOfBirth",
"babyIndex",
"gender",
"eatFunc",
"contentLike",
"productLike",
"specialAttention",
"channel",
],
};
const formItemFilter = (item) => {
return FormMap[formData.value.currentBaby].includes(item.name);
};
const formItems = [
{
label: "当前状态",
......@@ -177,7 +211,7 @@ const formItems = [
required: true,
placeholder: "请选择当前状态",
type: "picker",
range: ["已出生", "未出生"],
range: ["已出生", "孕中", "备孕"],
},
{
label: "宝宝昵称",
......@@ -191,7 +225,16 @@ const formItems = [
name: "dateOfBirth",
required: true,
placeholder: "请选择出生日期",
type: "input",
type: "picker",
mode: "date",
},
{
label: "预产日期",
name: "dateOfBirth2",
required: true,
placeholder: "请选择预产日期",
type: "picker",
mode: "date",
},
{
label: "宝宝胎数",
......@@ -200,6 +243,7 @@ const formItems = [
placeholder: "请选择胎数",
type: "picker",
range: ["单胎", "二胎", "多胎"],
mode: "custom",
},
{
label: "性别",
......@@ -208,6 +252,7 @@ const formItems = [
placeholder: "请选择性别",
type: "picker",
range: ["男", "女"],
mode: "custom",
},
{
label: "喂养方式",
......@@ -216,6 +261,14 @@ const formItems = [
placeholder: "请选择喂养方式",
type: "picker",
range: ["纯母乳", "混合", "奶粉"],
mode: "custom",
},
{
label: "孕周",
name: "yz",
required: false,
placeholder: "请选择",
type: "input",
},
{
label: "内容偏好",
......@@ -245,19 +298,51 @@ const formItems = [
placeholder: "请选择常购买渠道",
type: "picker",
range: ["电商", "母婴店", "超市"],
mode: "custom",
},
];
const getPickerIndex = (item) => {
const val = formData.value[item.name];
return val ? item.range.indexOf(val) : 0;
if (item.mode === "date") {
// val 形如 '2024-06-01'
if (typeof val === "string" && val.match(/^\d{4}-\d{2}-\d{2}$/)) {
const [year, month, day] = val.split("-").map(Number);
const currentYear = new Date().getFullYear();
const yearIdx = year - 1970;
const monthIdx = month - 1;
const dayIdx = day - 1;
return [yearIdx, monthIdx, dayIdx];
}
// 默认选中今年1月1日
const currentYear = new Date().getFullYear();
return [currentYear - 1970, 0, 0];
} else if (Array.isArray(item.range?.[0])) {
// 多列自定义选择
if (Array.isArray(val)) {
return val.map((v, col) => item.range[col].indexOf(v));
}
// 默认选中每列第一个
return item.range.map(() => 0);
} else {
// 单列自定义选择
return val ? item.range.indexOf(val) : 0;
}
};
const onPickerChange = (e, name) => {
const item = formItems.find((i) => i.name === name);
console.log(item.range, item, e);
formData.value[name] = item.range[e];
// 日期选择(mode="date"),e 为字符串
if (item.mode === "date") {
formData.value[name] = e;
} else if (Array.isArray(e)) {
// 多列自定义选择
formData.value[name] = e.map((idx, col) => item.range[col][idx]).join(" ");
} else {
// 单列自定义选择
formData.value[name] = item.range[e];
}
};
const onRadioChange = (e, name) => {
formData.value[name] = e.detail.value;
......@@ -277,6 +362,17 @@ const handleFormBottomBtn = () => {
const onChooseAvatar = (e) => {
formData.value.avatarUrl = e.detail.avatarUrl;
};
watch(
() => formData.value.currentBaby,
(newVal) => {
if (newVal === "已出生") {
pageStatus.value.formStatus = 2;
} else {
pageStatus.value.formStatus = 0;
}
}
);
</script>
<style lang="less" scoped>
......@@ -343,12 +439,12 @@ const onChooseAvatar = (e) => {
align-items: center;
justify-content: center;
.avatar-wrapper {
display: flex;
align-items: center;
justify-content: center;
padding: 0;
}
.avatar-wrapper {
display: flex;
align-items: center;
justify-content: center;
padding: 0;
}
.person-avatar-img {
width: 126rpx;
......
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