Commit 85291c3f authored by tao.huang's avatar tao.huang

feat: 多选

parent 5b57105a
<template> <template>
<Layer <Layer
:modelValue="modelValue" :modelValue="modelValue"
:title="title" :customHeader="true"
:showCancel="true" :showCancel="false"
:showConfirm="true" :showConfirm="false"
@update:modelValue="$emit('update:modelValue', $event)" @update:modelValue="$emit('update:modelValue', $event)"
@confirm="onConfirm" @confirm="onConfirm"
@cancel="onCancel" @cancel="onCancel"
> >
<template> <template>
<view class="multi-select-title">{{ title }}</view>
<view class="multi-select-list"> <view class="multi-select-list">
<view <view
v-for="opt in options" v-for="opt in options"
...@@ -21,18 +22,22 @@ ...@@ -21,18 +22,22 @@
<image <image
v-if="selectedSet.has(opt)" v-if="selectedSet.has(opt)"
class="check-icon" class="check-icon"
src="/static/check.png" :src="$baseUrl + 'person/icon_gou.png'"
/> />
</view> </view>
</view> </view>
<view class="multi-select-btn" @click="onConfirm"> 保存 </view>
</template> </template>
</Layer> </Layer>
</template> </template>
<script setup> <script setup>
import { ref, watch, computed } from "vue"; import { ref, watch, computed, getCurrentInstance } from "vue";
import Layer from "./Layer.vue"; import Layer from "./Layer.vue";
const { proxy } = getCurrentInstance();
const $baseUrl = proxy.$baseUrl;
const props = defineProps({ const props = defineProps({
modelValue: Boolean, modelValue: Boolean,
title: String, title: String,
...@@ -40,7 +45,12 @@ const props = defineProps({ ...@@ -40,7 +45,12 @@ const props = defineProps({
modelSelected: { type: Array, default: () => [] }, modelSelected: { type: Array, default: () => [] },
max: Number, max: Number,
}); });
const emit = defineEmits(["update:modelValue", "update:selected", "confirm", "cancel"]); const emit = defineEmits([
"update:modelValue",
"update:selected",
"confirm",
"cancel",
]);
const selected = ref([...props.modelSelected]); const selected = ref([...props.modelSelected]);
watch( watch(
...@@ -72,32 +82,50 @@ function onCancel() { ...@@ -72,32 +82,50 @@ function onCancel() {
</script> </script>
<style lang="less" scoped> <style lang="less" scoped>
.multi-select-btn {
width: 686rpx;
height: 94rpx;
background: #d3a358;
color: #fff;
border-radius: 46rpx;
display: flex;
align-items: center;
justify-content: center;
margin: 0 auto;
margin-top: 24rpx;
font-size: 32rpx;
}
.multi-select-title {
font-size: 32rpx;
color: #222;
font-weight: bold;
margin-bottom: 24rpx;
}
.multi-select-list { .multi-select-list {
display: flex; display: flex;
flex-wrap: wrap; flex-wrap: wrap;
gap: 24rpx 20rpx; gap: 15rpx 20rpx;
} }
.multi-select-tag { .multi-select-tag {
display: flex; display: flex;
align-items: center; align-items: center;
padding: 0 32rpx; padding: 0 24rpx;
height: 56rpx; height: 56rpx;
background: #fff; background: #ffffff;
border-radius: 28rpx; border-radius: 28rpx;
color: #222; color: #1d1e25;
font-size: 28rpx; font-size: 24rpx;
margin-bottom: 24rpx;
position: relative; position: relative;
border: 1rpx solid #eee;
.check-icon { .check-icon {
width: 28rpx; width: 19rpx;
height: 28rpx; height: 19rpx;
margin-left: 8rpx; position: absolute;
right: 2rpx;
top: 3rpx;
display: block;
} }
&.selected { &.selected {
background: #e9d3b1; background: #efe7da;
color: #b88a3a;
border: 1rpx solid #b88a3a;
} }
} }
</style> </style>
\ No newline at end of file
...@@ -21,7 +21,7 @@ ...@@ -21,7 +21,7 @@
<picker-view <picker-view
class="picker-layer-view" class="picker-layer-view"
mask-style="background: rgb(246, 248, 250); z-index: 0;" mask-style="background: rgb(246, 248, 250); z-index: 0;"
indicator-style="border-radius: 10px; height: 50px;background:#ffffff; z-index:0" indicator-style="border-radius: 10px; height: 50px; background:#ffffff; z-index:0"
:value="pickerValue" :value="pickerValue"
@change="onChange" @change="onChange"
> >
...@@ -55,9 +55,9 @@ ...@@ -55,9 +55,9 @@
</picker-view-column> </picker-view-column>
</template> </template>
<template v-else> <template v-else>
<picker-view-column v-for="(col, colIdx) in columns" :key="colIdx"> <picker-view-column>
<view <view
v-for="(item, idx) in col" v-for="(item, idx) in columns[0]"
:key="idx" :key="idx"
class="picker-layer-item" class="picker-layer-item"
> >
...@@ -309,6 +309,7 @@ function onChange(e) { ...@@ -309,6 +309,7 @@ function onChange(e) {
overflow: hidden; overflow: hidden;
display: flex; display: flex;
flex-direction: column; flex-direction: column;
position: relative;
} }
.picker-layer-header { .picker-layer-header {
display: flex; display: flex;
...@@ -350,6 +351,7 @@ function onChange(e) { ...@@ -350,6 +351,7 @@ function onChange(e) {
.picker-layer-view { .picker-layer-view {
flex: 1; flex: 1;
width: 100%; width: 100%;
height: 100%;
} }
.picker-layer-item { .picker-layer-item {
height: 100rpx; height: 100rpx;
......
...@@ -55,7 +55,7 @@ ...@@ -55,7 +55,7 @@
.filter(formItemFilter) .filter(formItemFilter)
.slice( .slice(
0, 0,
formData.currentBaby == '已出生' && pageStatus.formStatus == 2 formData.currentBaby == 2 && pageStatus.formStatus == 2
? 6 ? 6
: formItems.length : formItems.length
)" )"
...@@ -95,7 +95,9 @@ ...@@ -95,7 +95,9 @@
:onStatusChange="onDateStatusChange" :onStatusChange="onDateStatusChange"
> >
<view class="form-input-box"> <view class="form-input-box">
<view class="form-input">{{ getLabelByValue(item, formData[item.name]) || item.placeholder }}</view> <view class="form-input">{{
getLabelByValue(item, formData[item.name]) || item.placeholder
}}</view>
<image <image
class="form-input-icon" class="form-input-icon"
:src="$baseUrl + 'person/icon_arrow_yellow_right.png'" :src="$baseUrl + 'person/icon_arrow_yellow_right.png'"
...@@ -103,10 +105,17 @@ ...@@ -103,10 +105,17 @@
</view> </view>
</picker-custom> </picker-custom>
<!-- 多选弹窗类型 --> <!-- 多选弹窗类型 -->
<view v-else-if="item.type === 'multi-picker'" @click="handleMultiPickerOpen(item)"> <view
v-else-if="item.type === 'multi-picker'"
@click="handleMultiPickerOpen(item)"
>
<view class="form-input-box"> <view class="form-input-box">
<view class="form-input"> <view class="form-input">
{{ (formData[item.name] && formData[item.name].split(',').join('、')) || item.placeholder }} {{
(formData[item.name] &&
formData[item.name].split(",").join("、")) ||
item.placeholder
}}
</view> </view>
<image <image
class="form-input-icon" class="form-input-icon"
...@@ -135,7 +144,7 @@ ...@@ -135,7 +144,7 @@
</block> </block>
<view <view
v-if="pageStatus.formStatus != 0" v-if="formData.currentBaby == 2"
class="form-bottom-btn" class="form-bottom-btn"
@click="handleFormBottomBtn" @click="handleFormBottomBtn"
> >
...@@ -166,8 +175,11 @@ ...@@ -166,8 +175,11 @@
<MultiSelectLayer <MultiSelectLayer
v-if="multiPickerStatus && currentMultiPickerName" v-if="multiPickerStatus && currentMultiPickerName"
v-model="multiPickerStatus" v-model="multiPickerStatus"
:title="formItems.find(i => i.name === currentMultiPickerName)?.label + '(多选)'" :title="
:options="formItems.find(i => i.name === currentMultiPickerName)?.range" formItems.find((i) => i.name === currentMultiPickerName)?.label +
'(多选)'
"
:options="formItems.find((i) => i.name === currentMultiPickerName)?.range"
:modelSelected="multiPickerSelected[currentMultiPickerName]" :modelSelected="multiPickerSelected[currentMultiPickerName]"
@confirm="handleMultiPickerConfirm" @confirm="handleMultiPickerConfirm"
@cancel="handleMultiPickerCancel" @cancel="handleMultiPickerCancel"
...@@ -177,20 +189,19 @@ ...@@ -177,20 +189,19 @@
<script setup> <script setup>
import { ref, watch, onMounted } from "vue"; import { ref, watch, onMounted } from "vue";
import { onLoad } from '@dcloudio/uni-app'; import { onLoad } from "@dcloudio/uni-app";
import { useUserStore } from '../../stores/user.js'; import { useUserStore } from "../../stores/user.js";
import PickerCustom from "../../components/PickerCustom.vue"; import PickerCustom from "../../components/PickerCustom.vue";
import MultiSelectLayer from "../../components/MultiSelectLayer.vue"; import MultiSelectLayer from "../../components/MultiSelectLayer.vue";
const userStore = useUserStore(); const userStore = useUserStore();
const pageType = ref('add'); const pageType = ref("add");
const pageStatus = ref({ const pageStatus = ref({
formStatus: 0, // 0: 隐藏 1: 展开, 2: 收起 formStatus: 0, // 0: 隐藏 1: 展开, 2: 收起
btnStatus: true, // 是否显示提交按钮 btnStatus: true, // 是否显示提交按钮
}); });
// 0备孕 1孕中 2出生 // 0备孕 1孕中 2出生
const formData = ref({ const formData = ref({
currentBaby: 2, currentBaby: 2,
...@@ -208,19 +219,19 @@ const formData = ref({ ...@@ -208,19 +219,19 @@ const formData = ref({
}); });
const babyTypeMap = [ const babyTypeMap = [
{ label: '一胎', value: 1 }, { label: "一胎", value: 1 },
{ label: '二胎', value: 2 }, { label: "二胎", value: 2 },
{ label: '三胎', value: 3 }, { label: "三胎", value: 3 },
]; ];
const babyStageMap = [ const babyStageMap = [
{ label: '备孕', value: 0 }, { label: "备孕", value: 0 },
{ label: '孕中', value: 1 }, { label: "孕中", value: 1 },
{ label: '已出生', value: 2 }, { label: "已出生", value: 2 },
]; ];
const babyGenderMap = [ const babyGenderMap = [
{ label: '男', value: 'M' }, { label: "男", value: "M" },
{ label: '女', value: 'F' }, { label: "女", value: "F" },
{ label: '其他', value: 'O' }, { label: "其他", value: "O" },
]; ];
const FormMap = { const FormMap = {
...@@ -253,18 +264,36 @@ const formItemFilter = (item) => { ...@@ -253,18 +264,36 @@ const formItemFilter = (item) => {
const MAX_NICKNAME_LENGTH = 10; const MAX_NICKNAME_LENGTH = 10;
watch(
() => formData.value.currentBaby,
(newVal) => {
pageStatus.value.formStatus = newVal == 2 ? 2 : 0;
}
);
const contentLikeOptions = [ const contentLikeOptions = [
'奶粉选择', '奶粉成分', '奶粉冲泡', '宝宝奶量', '生长发育', '常见疾病', '体检疫苗', '饮食营养补充', '辅食营养', '亲子关系', '早教游戏' "奶粉选择",
"奶粉成分",
"奶粉冲泡",
"宝宝奶量",
"生长发育",
"常见疾病",
"体检疫苗",
"饮食营养补充",
"辅食营养",
"亲子关系",
"早教游戏",
]; ];
const productLikeOptions = [ const productLikeOptions = [
'飞鹤星飞帆', '星飞帆卓睿', '星飞帆卓耀', '星飞帆卓初', '星飞帆臻稚卓蓓', '星飞帆淳芮有机' "飞鹤星飞帆",
]; "星飞帆卓睿",
const specialAttentionOptions = [ "星飞帆卓耀",
'过敏', '长肉', '肠道', '消化', '脑发育' "星飞帆卓初",
]; "星飞帆臻稚卓蓓",
const channelOptions = [ "星飞帆淳芮有机",
'电商(京东/天猫)', '母婴店'
]; ];
const specialAttentionOptions = ["过敏", "长肉", "肠道", "消化", "脑发育"];
const channelOptions = ["电商(京东/天猫)", "母婴店"];
const formItems = [ const formItems = [
{ {
...@@ -273,7 +302,7 @@ const formItems = [ ...@@ -273,7 +302,7 @@ const formItems = [
required: true, required: true,
placeholder: "请选择当前状态", placeholder: "请选择当前状态",
type: "picker", type: "picker",
range: babyStageMap.map(i => i.label), range: babyStageMap.map((i) => i.label),
mode: "custom", mode: "custom",
}, },
{ {
...@@ -307,7 +336,7 @@ const formItems = [ ...@@ -307,7 +336,7 @@ const formItems = [
required: true, required: true,
placeholder: "未选择", placeholder: "未选择",
type: "picker", type: "picker",
range: babyTypeMap.map(i => i.label), range: babyTypeMap.map((i) => i.label),
mode: "custom", mode: "custom",
disabled: false, disabled: false,
}, },
...@@ -317,7 +346,7 @@ const formItems = [ ...@@ -317,7 +346,7 @@ const formItems = [
required: true, required: true,
placeholder: "未选择", placeholder: "未选择",
type: "picker", type: "picker",
range: babyGenderMap.map(i => i.label), range: babyGenderMap.map((i) => i.label),
mode: "custom", mode: "custom",
}, },
{ {
...@@ -376,16 +405,16 @@ const formItems = [ ...@@ -376,16 +405,16 @@ const formItems = [
const getPickerIndex = (item) => { const getPickerIndex = (item) => {
const val = formData.value[item.name]; const val = formData.value[item.name];
if (item.name === 'currentBaby') { if (item.name === "currentBaby") {
const idx = babyStageMap.findIndex(i => i.value === val); const idx = babyStageMap.findIndex((i) => i.value === val);
return idx > -1 ? idx : 0; return idx > -1 ? idx : 0;
} }
if (item.name === 'babyIndex') { if (item.name === "babyIndex") {
const idx = babyTypeMap.findIndex(i => i.value === val); const idx = babyTypeMap.findIndex((i) => i.value === val);
return idx > -1 ? idx : 0; return idx > -1 ? idx : 0;
} }
if (item.name === 'gender') { if (item.name === "gender") {
const idx = babyGenderMap.findIndex(i => i.value === val); const idx = babyGenderMap.findIndex((i) => i.value === val);
return idx > -1 ? idx : 0; return idx > -1 ? idx : 0;
} }
if (item.mode === "date") { if (item.mode === "date") {
...@@ -410,15 +439,15 @@ const getPickerIndex = (item) => { ...@@ -410,15 +439,15 @@ const getPickerIndex = (item) => {
}; };
const onPickerChange = (e, name) => { const onPickerChange = (e, name) => {
const item = formItems.find((i) => i.name === name); const item = formItems.find((i) => i.name === name);
if (name === 'currentBaby') { if (name === "currentBaby") {
formData.value[name] = babyStageMap[e].value; formData.value[name] = babyStageMap[e].value;
return; return;
} }
if (name === 'babyIndex') { if (name === "babyIndex") {
formData.value[name] = babyTypeMap[e].value; formData.value[name] = babyTypeMap[e].value;
return; return;
} }
if (name === 'gender') { if (name === "gender") {
formData.value[name] = babyGenderMap[e].value; formData.value[name] = babyGenderMap[e].value;
return; return;
} }
...@@ -448,43 +477,30 @@ const onChooseAvatar = (e) => { ...@@ -448,43 +477,30 @@ const onChooseAvatar = (e) => {
formData.value.avatarUrl = e.detail.avatarUrl; formData.value.avatarUrl = e.detail.avatarUrl;
}; };
watch(
() => formData.value.currentBaby,
(newVal) => {
if (newVal === "已出生") {
pageStatus.value.formStatus = 2;
} else {
pageStatus.value.formStatus = 0;
}
}
);
function onDateStatusChange(status) { function onDateStatusChange(status) {
if (status === '已出生' || status === '孕中') {
formData.value.currentBaby = status; formData.value.currentBaby = status;
}
} }
// getLabelByValue 支持所有映射字段 // getLabelByValue 支持所有映射字段
const getLabelByValue = (item, value) => { const getLabelByValue = (item, value) => {
if (item.name === 'currentBaby') { if (item.name === "currentBaby") {
return babyStageMap.find(i => i.value === value)?.label || ''; return babyStageMap.find((i) => i.value === value)?.label || "";
} }
if (item.name === 'babyIndex') { if (item.name === "babyIndex") {
return babyTypeMap.find(i => i.value === value)?.label || ''; return babyTypeMap.find((i) => i.value === value)?.label || "";
} }
if (item.name === 'gender') { if (item.name === "gender") {
return babyGenderMap.find(i => i.value === value)?.label || ''; return babyGenderMap.find((i) => i.value === value)?.label || "";
} }
return value; return value;
}; };
const getValueByLabel = (map, label) => { const getValueByLabel = (map, label) => {
const found = map.find(i => i.label === label); const found = map.find((i) => i.label === label);
return found ? found.value : ''; return found ? found.value : "";
}; };
const multiPickerStatus = ref(false); // 控制弹窗显示 const multiPickerStatus = ref(false); // 控制弹窗显示
const currentMultiPickerName = ref(''); // 当前弹窗对应的item.name const currentMultiPickerName = ref(""); // 当前弹窗对应的item.name
const multiPickerSelected = ref({}); // 存储每个multi-picker的选中项 const multiPickerSelected = ref({}); // 存储每个multi-picker的选中项
function handleMultiPickerOpen(item) { function handleMultiPickerOpen(item) {
...@@ -492,54 +508,58 @@ function handleMultiPickerOpen(item) { ...@@ -492,54 +508,58 @@ function handleMultiPickerOpen(item) {
multiPickerStatus.value = true; multiPickerStatus.value = true;
// 初始化选中项 // 初始化选中项
let val = formData.value[item.name]; let val = formData.value[item.name];
if (typeof val === 'string') { if (typeof val === "string") {
val = val ? val.split(',') : []; val = val ? val.split(",") : [];
} }
multiPickerSelected.value[item.name] = val || []; multiPickerSelected.value[item.name] = val || [];
} }
function handleMultiPickerConfirm(selected) { function handleMultiPickerConfirm(selected) {
if (!currentMultiPickerName.value) return; if (!currentMultiPickerName.value) return;
formData.value[currentMultiPickerName.value] = selected.join(','); formData.value[currentMultiPickerName.value] = selected.join(",");
multiPickerStatus.value = false; multiPickerStatus.value = false;
currentMultiPickerName.value = ''; currentMultiPickerName.value = "";
} }
function handleMultiPickerCancel() { function handleMultiPickerCancel() {
multiPickerStatus.value = false; multiPickerStatus.value = false;
currentMultiPickerName.value = ''; currentMultiPickerName.value = "";
} }
onLoad((options) => { onLoad((options) => {
pageType.value = options.type || 'add'; pageType.value = options.type || "add";
if (pageType.value === 'edit') { if (pageType.value === "edit") {
const baby = userStore.babyInfo; const baby = userStore.babyInfo;
formData.value.currentBaby = baby.babyStage ?? 2; formData.value.currentBaby = baby.babyStage ?? 2;
formData.value.nickName = baby.babyName || ''; formData.value.nickName = baby.babyName || "";
formData.value.dateOfBirth = baby.content?.babyBirthday || ''; formData.value.dateOfBirth = baby.content?.babyBirthday || "";
formData.value.dateOfBirth2 = baby.content?.dueDate || ''; formData.value.dateOfBirth2 = baby.content?.dueDate || "";
formData.value.babyIndex = baby.content?.babyType ?? 1; formData.value.babyIndex = baby.content?.babyType ?? 1;
formData.value.gender = baby.content?.babyGender ?? 'M'; formData.value.gender = baby.content?.babyGender ?? "M";
formData.value.eatFunc = baby.content?.feedingType || ''; formData.value.eatFunc = baby.content?.feedingType || "";
formData.value.contentLike = baby.content?.contentPreference || ''; formData.value.contentLike = baby.content?.contentPreference || "";
formData.value.productLike = baby.content?.productPreference || ''; formData.value.productLike = baby.content?.productPreference || "";
formData.value.specialAttention = baby.content?.followInfo || ''; formData.value.specialAttention = baby.content?.followInfo || "";
formData.value.channel = baby.content?.purchaseChannel || ''; formData.value.channel = baby.content?.purchaseChannel || "";
formData.value.avatarUrl = baby.babyAvatar || ''; formData.value.avatarUrl = baby.babyAvatar || "";
} else { } else {
Object.assign(formData.value, { Object.assign(formData.value, {
currentBaby: 2, currentBaby: 2,
nickName: '', nickName: "",
dateOfBirth: '', dateOfBirth: "",
dateOfBirth2: '', dateOfBirth2: "",
gender: '', gender: "",
babyIndex: '', babyIndex: "",
eatFunc: '', eatFunc: "",
contentLike: '', contentLike: "",
productLike: '', productLike: "",
specialAttention: '', specialAttention: "",
channel: '', channel: "",
avatarUrl: '', avatarUrl: "",
}); });
} }
if (formData.value.currentBaby == 2) {
pageStatus.value.formStatus = 2;
}
}); });
</script> </script>
......
...@@ -69,7 +69,7 @@ ...@@ -69,7 +69,7 @@
<BabySwitcher <BabySwitcher
v-if="showBabySwitcher" v-if="showBabySwitcher"
:show="showBabySwitcher" :show="showBabySwitcher"
:babyList="babyInfo.allBabyBaseInfo" :babyList="babyInfo.allBabyBaseInfo || []"
:addIcon="$baseUrl + 'my/baby_add_btn.png'" :addIcon="$baseUrl + 'my/baby_add_btn.png'"
@close="showBabySwitcher = false" @close="showBabySwitcher = false"
@select="onSelectBaby" @select="onSelectBaby"
......
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