489 lines
12 KiB
Vue
489 lines
12 KiB
Vue
<template>
|
||
<view class="common-filter">
|
||
<!-- 筛选触发按钮(服务时间 + 主筛选) -->
|
||
<view class="filter-btns-wrap">
|
||
<!-- 服务时间按钮 -->
|
||
<view class="filter-trigger time-trigger" @click="toggleTimePopup">
|
||
<text class="filter-text" :class="{ active: timePopupShow }">
|
||
{{ timeBtnText }}
|
||
</text>
|
||
<image
|
||
:src="!timePopupShow ? sqIcon : zkIcon"
|
||
mode="aspectFit"
|
||
class="time-icon"
|
||
></image>
|
||
</view>
|
||
|
||
<!-- 原筛选按钮 -->
|
||
<view class="filter-trigger main-filter-trigger time-trigger" @click="toggleMainPopup">
|
||
<text class="filter-text" :class="{ active: mainPopupShow }">
|
||
{{ filterBtnText }}
|
||
</text>
|
||
<image
|
||
:src="!mainPopupShow ? sqIcon : zkIcon"
|
||
mode="aspectFit"
|
||
class="time-icon"
|
||
></image>
|
||
</view>
|
||
</view>
|
||
<filterPopup
|
||
ref="filterPopupRef"
|
||
v-model="mainPopupShow"
|
||
:filterList="filterList"
|
||
@reset="resetFilter"
|
||
@sure="$emit('search')"
|
||
>
|
||
<filterCard
|
||
v-for="info in filterList"
|
||
:info="info"
|
||
v-model="value"
|
||
@selectDetail="(value) => selectDetail(info.type, value)"
|
||
:isSingle="true"
|
||
:infoDetailList="info"
|
||
>
|
||
<view class="price-input" v-if="info.type == 'price'">
|
||
<input
|
||
type="number"
|
||
:value="value.start_price"
|
||
@input="(e) => selectDetail('start_price', [e.detail.value])"
|
||
placeholder="最低价"
|
||
class="price-input-field"
|
||
/>
|
||
<text class="price-separator"></text>
|
||
<input
|
||
type="number"
|
||
:value="value.end_price"
|
||
@input="(e) => selectDetail('end_price', [e.detail.value])"
|
||
placeholder="最高价"
|
||
class="price-input-field"
|
||
/>
|
||
</view>
|
||
</filterCard>
|
||
</filterPopup>
|
||
<view class="time-filter-popup" :class="{ show: timePopupShow }">
|
||
<view class="time-filter-content">
|
||
<view
|
||
class="time-option"
|
||
v-for="(item, index) in timeOptions"
|
||
:key="index"
|
||
:class="{ active: selectedTimeOption === index }"
|
||
@click="changeTime(index)"
|
||
>
|
||
<text class="time-text">{{ item.text }}</text>
|
||
<!-- <text class="time-discount" v-if="item.discount">{{ item.discount }}</text> -->
|
||
</view>
|
||
</view>
|
||
</view>
|
||
</view>
|
||
</template>
|
||
|
||
<script>
|
||
import filterPopup from "@/components/filter-popup/filter-popup.vue";
|
||
import filterCard from "@/components/filterCard/filterCard.vue";
|
||
export default {
|
||
name: "CommonFilter",
|
||
props: {
|
||
// 服务时间按钮文本
|
||
timeBtnText: {
|
||
type: String,
|
||
default: "服务时间",
|
||
},
|
||
// 服务时间展开/收起图标
|
||
sqIcon: {
|
||
type: String,
|
||
default:
|
||
"https://mrrplus.oss-cn-beijing.aliyuncs.com/wxstaic/images/sq_icon.png",
|
||
},
|
||
zkIcon: {
|
||
type: String,
|
||
default:
|
||
"https://mrrplus.oss-cn-beijing.aliyuncs.com/wxstaic/images/zk_icon.png",
|
||
},
|
||
// 主筛选按钮文本
|
||
filterBtnText: {
|
||
type: String,
|
||
default: "筛选",
|
||
},
|
||
// 主筛选图标
|
||
filterIcon: {
|
||
type: String,
|
||
default:
|
||
"https://mrrplus.oss-cn-beijing.aliyuncs.com/wxstaic/images/filter_icon.png",
|
||
},
|
||
filterDetailsLists: {
|
||
type: Array,
|
||
default: () => [
|
||
{
|
||
id: 2,
|
||
title: "价格",
|
||
type: "price",
|
||
details: [
|
||
{
|
||
id: 1,
|
||
name: "0-10元",
|
||
value: "0-10",
|
||
},
|
||
{
|
||
id: 2,
|
||
name: "10-30元",
|
||
value: "10-30",
|
||
},
|
||
{
|
||
id: 3,
|
||
name: "30-50元",
|
||
value: "30-50",
|
||
},
|
||
{
|
||
id: 4,
|
||
name: "50-100元",
|
||
value: "50-100",
|
||
},
|
||
{
|
||
id: 5,
|
||
name: "100-300元",
|
||
value: "100-300",
|
||
},
|
||
{
|
||
id: 6,
|
||
name: "300+",
|
||
value: "300-",
|
||
},
|
||
],
|
||
},
|
||
{
|
||
id: 3,
|
||
title: "排序",
|
||
type: "ordersort",
|
||
details: [
|
||
{
|
||
id: 1,
|
||
name: " 销量最高",
|
||
value: "1",
|
||
},
|
||
{
|
||
id: 2,
|
||
name: "价格最高",
|
||
value: "2",
|
||
},
|
||
{
|
||
id: 3,
|
||
name: "价格最低",
|
||
value: "3",
|
||
},
|
||
],
|
||
},
|
||
{
|
||
id: 4,
|
||
title: "服务类型",
|
||
type: "server_kind",
|
||
details: [
|
||
{
|
||
id: 1,
|
||
name: " 到家",
|
||
value: "1",
|
||
},
|
||
{
|
||
id: 2,
|
||
name: "到店",
|
||
value: "2",
|
||
},
|
||
],
|
||
},
|
||
],
|
||
},
|
||
value: {
|
||
type: Object,
|
||
default: () => {},
|
||
},
|
||
},
|
||
components: { filterPopup, filterCard },
|
||
computed: {
|
||
filterList() {
|
||
return this.filterDetailsLists.map((item) => {
|
||
if (item.type == "price") {
|
||
return {
|
||
...item,
|
||
defaultValue: [
|
||
`${this.value.start_price || ""}-${this.value.end_price || ""}`,
|
||
],
|
||
};
|
||
}
|
||
return {
|
||
...item,
|
||
defaultValue: [this.value[item.type]],
|
||
};
|
||
});
|
||
},
|
||
},
|
||
data() {
|
||
return {
|
||
timePopupShow: false, // 服务时间弹框显示状态(当前模板未实现弹框内容)
|
||
mainPopupShow: false, // 主筛选弹框显示状态(当前模板未实现弹框内容)
|
||
timeOptions: [
|
||
{ text: "今日可约" },
|
||
{ text: "近两日可约", discount: "64.31%" },
|
||
{ text: "近三日可约" },
|
||
],
|
||
selectedTimeOption: undefined,
|
||
};
|
||
},
|
||
methods: {
|
||
changeTime(index) {
|
||
this.selectedTimeOption = index;
|
||
this.selectDetail("date", [this.getDate(index)]);
|
||
this.$emit("search");
|
||
this.timePopupShow = false;
|
||
},
|
||
getDate(index) {
|
||
//今天的时间
|
||
var day1 = new Date();
|
||
day1.setTime(day1.getTime());
|
||
var m1 = day1.getMonth() + 1;
|
||
if (m1 <= 9) {
|
||
m1 = "0" + m1;
|
||
}
|
||
var d1 = day1.getDate();
|
||
if (d1 <= 9) {
|
||
d1 = "0" + d1;
|
||
}
|
||
var s1 = day1.getFullYear() + "-" + m1 + "-" + d1;
|
||
|
||
//明天的时间
|
||
var day2 = new Date();
|
||
day2.setTime(day2.getTime() + 24 * 60 * 60 * 1000);
|
||
var m2 = day2.getMonth() + 1;
|
||
if (m2 <= 9) {
|
||
m2 = "0" + m2;
|
||
}
|
||
var d2 = day2.getDate();
|
||
if (d2 <= 9) {
|
||
d2 = "0" + d2;
|
||
}
|
||
var s2 = day2.getFullYear() + "-" + m2 + "-" + d2;
|
||
|
||
//后天的时间
|
||
var day3 = new Date();
|
||
day3.setTime(day3.getTime() + 24 * 60 * 60 * 1000 * 2);
|
||
var m3 = day3.getMonth() + 1;
|
||
if (m3 <= 9) {
|
||
m3 = "0" + m3;
|
||
}
|
||
var d3 = day3.getDate();
|
||
if (d3 <= 9) {
|
||
d3 = "0" + d3;
|
||
}
|
||
var s3 = day3.getFullYear() + "-" + m3 + "-" + d3;
|
||
|
||
if (index == 0) {
|
||
return [`${s1}`];
|
||
} else if (index == 1) {
|
||
return [`${s1}`, `${s2}`];
|
||
} else if (index == 2) {
|
||
return [`${s1}`, `${s2}`, `${s3}`];
|
||
}
|
||
},
|
||
resetFilter() {
|
||
const resetObj = {};
|
||
this.filterDetailsLists.forEach((it) => {
|
||
if (it.type === "price") {
|
||
resetObj.start_price = undefined;
|
||
resetObj.end_price = undefined;
|
||
} else {
|
||
resetObj[it.type] = undefined;
|
||
}
|
||
});
|
||
this.$emit("input", {
|
||
...this.value,
|
||
...resetObj,
|
||
});
|
||
this.$emit("search");
|
||
},
|
||
// 切换服务时间弹框(弹框内容需后续补充)
|
||
toggleTimePopup() {
|
||
this.timePopupShow = !this.timePopupShow;
|
||
if (this.timePopupShow) this.mainPopupShow = false; // 互斥显示
|
||
},
|
||
// 切换主筛选弹框(弹框内容需后续补充)
|
||
toggleMainPopup() {
|
||
if (this.$refs.filterPopupRef) {
|
||
if (!this.mainPopupShow) {
|
||
this.timePopupShow = false;
|
||
this.mainPopupShow = true;
|
||
} else {
|
||
this.timePopupShow = false; // 互斥显示
|
||
}
|
||
}
|
||
},
|
||
selectDetail(type, value) {
|
||
console.log(type, value);
|
||
if (type == "price") {
|
||
if (value[0]) {
|
||
let priceList = value[0].split("-");
|
||
this.$emit("input", {
|
||
...this.value,
|
||
start_price: priceList[0],
|
||
end_price: priceList[1],
|
||
});
|
||
} else {
|
||
this.$emit("input", {
|
||
...this.value,
|
||
start_price: undefined,
|
||
end_price: undefined,
|
||
});
|
||
}
|
||
} else {
|
||
this.$emit("input", {
|
||
...this.value,
|
||
[type]: value[0],
|
||
});
|
||
}
|
||
},
|
||
},
|
||
};
|
||
</script>
|
||
|
||
<style lang="less" scoped>
|
||
.common-filter {
|
||
position: relative;
|
||
z-index: 900;
|
||
background-color: #fff;
|
||
height: 102rpx;
|
||
display: flex;
|
||
align-items: center;
|
||
/* 服务时间弹框样式 */
|
||
.time-filter-popup {
|
||
width: 750rpx;
|
||
background-color: #ffffff;
|
||
height: 0;
|
||
opacity: 0;
|
||
transition: all 0.3s ease;
|
||
box-shadow: 0 4rpx 12rpx rgba(0, 0, 0, 0.1);
|
||
visibility: hidden;
|
||
border-radius: 0 0 20rpx 20rpx;
|
||
overflow: hidden;
|
||
position: absolute;
|
||
z-index: 10;
|
||
top: 102rpx;
|
||
left: 0;
|
||
right: 0;
|
||
}
|
||
|
||
.time-filter-popup.show {
|
||
opacity: 1;
|
||
height: 320rpx;
|
||
visibility: visible;
|
||
}
|
||
|
||
.time-filter-content {
|
||
padding: 0;
|
||
}
|
||
|
||
.time-option {
|
||
display: flex;
|
||
justify-content: space-between;
|
||
align-items: center;
|
||
padding: 32rpx;
|
||
background-color: #ffffff;
|
||
position: relative;
|
||
}
|
||
|
||
.time-option:not(:last-child)::after {
|
||
content: "";
|
||
position: absolute;
|
||
left: 32rpx;
|
||
right: 32rpx;
|
||
bottom: 0;
|
||
height: 1rpx;
|
||
background-color: #eeeeee;
|
||
}
|
||
|
||
.time-option.active {
|
||
background-color: #fff5f6;
|
||
}
|
||
|
||
.time-option.active .time-text {
|
||
color: #FF4767;
|
||
font-weight: 500;
|
||
}
|
||
|
||
.time-text {
|
||
font-size: 28rpx;
|
||
color: #333333;
|
||
}
|
||
|
||
.time-discount {
|
||
font-size: 24rpx;
|
||
color: #FF4767;
|
||
padding: 4rpx 12rpx;
|
||
background-color: #fff5f6;
|
||
border-radius: 20rpx;
|
||
}
|
||
}
|
||
/* 筛选按钮容器:横向排列两个按钮,控制间距和内边距 */
|
||
.filter-btns-wrap {
|
||
width: 100%;
|
||
display: flex;
|
||
justify-content: space-between;
|
||
align-items: center;
|
||
gap: 24rpx;
|
||
padding: 0 24rpx;
|
||
}
|
||
|
||
/* 基础筛选按钮样式:统一按钮的flex布局、对齐方式和行高 */
|
||
.filter-trigger {
|
||
display: flex;
|
||
align-items: center;
|
||
gap: 8rpx;
|
||
height: 60rpx;
|
||
line-height: 60rpx;
|
||
}
|
||
|
||
/* 按钮文本样式:默认灰色,选中时高亮 */
|
||
.filter-text {
|
||
font-size: 28rpx;
|
||
color: #666;
|
||
}
|
||
.active {
|
||
color: #FF4767; /* 选中态主题色 */
|
||
}
|
||
|
||
/* 服务时间按钮专属:控制下拉图标尺寸 */
|
||
.time-trigger .time-icon {
|
||
width: 16rpx;
|
||
height: 16rpx;
|
||
}
|
||
|
||
/* 主筛选按钮专属:控制筛选图标尺寸 */
|
||
.main-filter-trigger .filter-icon {
|
||
width: 32rpx;
|
||
height: 32rpx;
|
||
}
|
||
//价格区间样式
|
||
.price-input {
|
||
display: flex;
|
||
justify-content: space-between;
|
||
align-items: center;
|
||
width: 370rpx;
|
||
height: 80rpx;
|
||
background: #f3f6f8;
|
||
border-radius: 10rpx;
|
||
|
||
.price-input-field {
|
||
width: 166rpx;
|
||
height: 80rpx;
|
||
line-height: 50rpx;
|
||
text-align: center;
|
||
border-radius: 26rpx;
|
||
font-size: 26rpx;
|
||
font-weight: 400;
|
||
color: #3d3d3d;
|
||
}
|
||
|
||
.price-separator {
|
||
height: 3rpx;
|
||
width: 38rpx;
|
||
background-color: #dddddd;
|
||
}
|
||
}
|
||
</style>
|