7 changed files with 370 additions and 183 deletions
@ -0,0 +1,205 @@ |
|||||
|
<template> |
||||
|
<div class="search-filter-bar"> |
||||
|
<van-search v-model="searchText" show-action placeholder="请输入关键字查询" clearable clear-trigger="always" |
||||
|
@clear="onClear" @search="onSearch"> |
||||
|
<template #action> |
||||
|
<div @click="onSearch">搜索</div> |
||||
|
</template> |
||||
|
</van-search> |
||||
|
|
||||
|
<div v-if="showDateFilter" class="search-button-list"> |
||||
|
<van-button plain hairline :class="dateType === null ? 'search-btn active' : 'search-btn'" |
||||
|
@click="searchDateType(null)" round type="primary" size="mini">全部</van-button> |
||||
|
<van-button plain hairline :class="dateType === 1 ? 'search-btn active' : 'search-btn'" |
||||
|
@click="searchDateType(1)" round type="primary" size="mini">本月</van-button> |
||||
|
<van-button plain hairline :class="dateType === 2 ? 'search-btn active' : 'search-btn'" |
||||
|
@click="searchDateType(2)" round type="primary" size="mini">本季</van-button> |
||||
|
<van-button plain hairline :class="dateType === 3 ? 'search-btn active' : 'search-btn'" |
||||
|
@click="searchDateType(3)" round type="primary" size="mini">本年</van-button> |
||||
|
<van-button plain hairline :class="dateType === 9 ? 'search-btn active' : 'search-btn'" |
||||
|
@click="openDatePicker" round type="primary" size="mini">筛选</van-button> |
||||
|
</div> |
||||
|
|
||||
|
<div v-if="showDateFilter" class="search-date-display" v-show="dateShow"> |
||||
|
<span class="date-label" @click="openDatePicker">{{ dateSearchDisplay }}</span> |
||||
|
</div> |
||||
|
|
||||
|
<van-popup v-if="showDateFilter" v-model:show="showDatePicker" position="bottom"> |
||||
|
<van-date-picker title="选择月度" v-model="currentDate" :min-date="minDate" :max-date="maxDate" |
||||
|
:columns-type="['year', 'month']" @confirm="onDateConfirm" @cancel="showDatePicker = false" /> |
||||
|
</van-popup> |
||||
|
</div> |
||||
|
</template> |
||||
|
|
||||
|
<script setup name="SearchFilterBar"> |
||||
|
import { ref, watch } from 'vue'; |
||||
|
|
||||
|
const props = defineProps({ |
||||
|
searchValue: { |
||||
|
type: String, |
||||
|
default: '' |
||||
|
}, |
||||
|
dateType: { |
||||
|
type: Number, |
||||
|
default: null |
||||
|
}, |
||||
|
dateSearch: { |
||||
|
type: String, |
||||
|
default: null |
||||
|
}, |
||||
|
showDateFilter: { |
||||
|
type: Boolean, |
||||
|
default: true |
||||
|
} |
||||
|
}); |
||||
|
|
||||
|
const emit = defineEmits(['search', 'clear', 'dateChange']); |
||||
|
|
||||
|
const searchText = ref(props.searchValue); |
||||
|
const dateType = ref(props.dateType); |
||||
|
const dateShow = ref(false); |
||||
|
const showDatePicker = ref(false); |
||||
|
const dateSearchDisplay = ref(''); |
||||
|
const currentDate = ref(['2026', '01']); |
||||
|
const minDate = new Date(2020, 0, 1); |
||||
|
const maxDate = new Date(2030, 11, 31); |
||||
|
|
||||
|
watch(() => props.dateType, (newVal) => { |
||||
|
dateType.value = newVal; |
||||
|
}); |
||||
|
|
||||
|
watch(() => props.dateSearch, (newVal) => { |
||||
|
if (newVal) { |
||||
|
const parts = newVal.split('-'); |
||||
|
if (parts.length >= 2) { |
||||
|
currentDate.value = [parts[0], parts[1]]; |
||||
|
dateSearchDisplay.value = `${parts[0]}/${parts[1]}`; |
||||
|
dateShow.value = true; |
||||
|
} |
||||
|
} else { |
||||
|
dateShow.value = false; |
||||
|
dateSearchDisplay.value = ''; |
||||
|
} |
||||
|
}); |
||||
|
|
||||
|
const onSearch = () => { |
||||
|
emit('search', { |
||||
|
searchValue: searchText.value, |
||||
|
dateType: props.dateType, |
||||
|
dateSearch: props.dateSearch |
||||
|
}); |
||||
|
}; |
||||
|
|
||||
|
const onClear = () => { |
||||
|
searchText.value = ''; |
||||
|
emit('clear'); |
||||
|
emit('search', { |
||||
|
searchValue: '', |
||||
|
dateType: props.dateType, |
||||
|
dateSearch: props.dateSearch |
||||
|
}); |
||||
|
}; |
||||
|
|
||||
|
const searchDateType = (val) => { |
||||
|
emit('dateChange', { |
||||
|
dateType: val, |
||||
|
dateSearch: null, |
||||
|
dateShow: false |
||||
|
}); |
||||
|
}; |
||||
|
|
||||
|
const openDatePicker = () => { |
||||
|
showDatePicker.value = true; |
||||
|
}; |
||||
|
|
||||
|
const onDateConfirm = (value) => { |
||||
|
const year = value.selectedValues[0]; |
||||
|
const month = value.selectedValues[1]; |
||||
|
dateSearchDisplay.value = year + '/' + month; |
||||
|
showDatePicker.value = false; |
||||
|
emit('dateChange', { |
||||
|
dateType: 9, |
||||
|
dateSearch: year + '-' + month, |
||||
|
dateShow: true |
||||
|
}); |
||||
|
}; |
||||
|
</script> |
||||
|
|
||||
|
<style lang="less" scoped> |
||||
|
.search-filter-bar { |
||||
|
:deep(.van-search) { |
||||
|
background: #fff; |
||||
|
padding: 12px 16px; |
||||
|
margin-bottom: -1px; |
||||
|
} |
||||
|
|
||||
|
:deep(.van-search__content) { |
||||
|
height: 0.9rem; |
||||
|
border: 1px solid #ececec; |
||||
|
border-radius: 0.15rem 0 0 0.15rem; |
||||
|
} |
||||
|
|
||||
|
:deep(.van-search__action) { |
||||
|
margin: 0 3% 0 0; |
||||
|
width: 10%; |
||||
|
height: 0.9rem; |
||||
|
background: #1367fe; |
||||
|
border: 1px solid #1367fe; |
||||
|
border-radius: 0 0.15rem 0.15rem 0; |
||||
|
color: #fff; |
||||
|
text-align: center; |
||||
|
line-height: 0.9rem; |
||||
|
} |
||||
|
|
||||
|
.search-button-list { |
||||
|
display: flex; |
||||
|
flex-direction: row; |
||||
|
padding: 0.2rem 0.27rem 0; |
||||
|
gap: 0.15rem; |
||||
|
margin-bottom: 8px; |
||||
|
|
||||
|
.search-btn { |
||||
|
flex: 1; |
||||
|
height: 0.7rem; |
||||
|
background: #ebebeb; |
||||
|
border-color: #ebebeb; |
||||
|
color: #999; |
||||
|
font-size: 0.3rem; |
||||
|
} |
||||
|
|
||||
|
.search-btn.active { |
||||
|
background-color: #d9e6fd; |
||||
|
border-color: #75a5fb; |
||||
|
color: #1367fe; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
.search-date-display { |
||||
|
padding: 0.15rem 0.27rem 0; |
||||
|
|
||||
|
.date-label { |
||||
|
color: #c1bfbf; |
||||
|
font-size: 0.4rem; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
/* ===== Vant 搜索框样式覆盖 ===== */ |
||||
|
:deep(.van-search__content) { |
||||
|
height: 0.9rem; |
||||
|
border: 1px solid #ececec; |
||||
|
border-radius: 0.15rem 0 0 0.15rem; |
||||
|
} |
||||
|
|
||||
|
:deep(.van-search__action) { |
||||
|
margin: 0 3% 0 0; |
||||
|
width: 10%; |
||||
|
height: 0.9rem; |
||||
|
background: #1367fe; |
||||
|
border: 0.01rem solid #1367fe; |
||||
|
border-radius: 0 0.15rem 0.15rem 0; |
||||
|
color: #fff; |
||||
|
text-align: center; |
||||
|
line-height: 0.9rem; |
||||
|
} |
||||
|
} |
||||
|
</style> |
||||
Loading…
Reference in new issue