mrr.sj.front/components/common/CommonFilter.vue

489 lines
12 KiB
Vue
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<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>