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: #E8101E;
|
|||
|
|
font-weight: 500;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
.time-text {
|
|||
|
|
font-size: 28rpx;
|
|||
|
|
color: #333333;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
.time-discount {
|
|||
|
|
font-size: 24rpx;
|
|||
|
|
color: #E8101E;
|
|||
|
|
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: #E8101E; /* 选中态主题色 */
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/* 服务时间按钮专属:控制下拉图标尺寸 */
|
|||
|
|
.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>
|