pad-app/components/fjj-condition/fjj-condition.vue

606 lines
17 KiB
Vue
Raw Normal View History

2023-07-13 11:18:17 +08:00
<template>
<view>
<uni-drawer :visible="visibleDrawer" :hideNoAnimate="showBackButton" mode="right" @close="closeDrawer()">
<!-- #ifdef APP-PLUS -->
<view class="iconfont icon-guanbi" v-if="showBackButton" @tap="closeDrawer()"></view>
<!-- #endif -->
<scroll-view class="drawer-list" scroll-y :style="{'height': drawerHeight, 'padding-top': fixTop}">
<block v-for="(item, index) in menuList" :key="index">
<!-- 单选多选 isMutiple是否支持多选-->
<view v-if="item.type === 'custom' && item.detailList.length">
<view class="drawer-list-title flex justify-between">
<view>
{{item.title}}
</view>
<text v-if="item.detailList.length>showLenght"
@tap="showMore(index)">{{item.showMoreList ? '收起' : '更多'}}</text>
</view>
<view class="draer-list-con">
<template v-if="!item.showMoreList">
<text
:style="{background: textItem.isSelected ? color : '', color: textItem.isSelected ? '#ffffff' : ''}"
v-if="idx<showLenght" v-for="(textItem, idx) in item.detailList" :key="idx"
:class="textItem.isSelected ? 'on' : ''"
@tap="itemTap(idx,item.detailList,item.key, item.isMutiple)">
{{textItem.title}}
</text>
</template>
<template v-else>
<text
:style="{background: textItem.isSelected ? color : '', color: textItem.isSelected ? '#ffffff' : ''}"
v-for="(textItem, idx) in item.detailList" :key="idx"
:class="textItem.isSelected ? 'on' : ''"
@tap="itemTap(idx,item.detailList,item.key, item.isMutiple)">
{{textItem.title}}
</text>
</template>
</view>
</view>
<!-- 时间带时分秒范围选择 -->
<view v-if="item.type === 'rangetime'">
<view class="drawer-list-title flex justify-between">
<view>
{{item.title}}
</view>
</view>
<view class="dateContent" @click="onShowDatePicker('rangetime', item.key, item)">
<view>
<template v-if="result[item.key] && result[item.key].length > 0">
{{result[item.key][0]}}
</template>
</view>
<view>
<template v-if="result[item.key] && result[item.key].length > 0">
{{result[item.key][1]}}
</template>
</view>
</view>
</view>
<!-- 时间不带时分秒范围选择 -->
<view v-if="item.type === 'range'">
<view class="drawer-list-title flex justify-between">
<view>
{{item.title}}
</view>
</view>
<view class="dateContent" @click="onShowDatePicker('range', item.key, item)">
<view>
<template v-if="result[item.key] && result[item.key].length > 0">
{{result[item.key][0]}}-{{result[item.key][1]}}
</template>
</view>
</view>
</view>
<!-- 时间选择 -->
<view v-if="item.type === 'date'">
<view class="drawer-list-title flex justify-between">
<view>
{{item.title}}
</view>
</view>
<view class="dateContent" @click="onShowDatePicker('date', item.key, item)">
<view>
<template v-if="result[item.key]">
{{result[item.key]}}
</template>
</view>
</view>
</view>
<!-- 数值范围选择 -->
<view v-if="item.type === 'rangenumber'">
<view class="drawer-list-title flex justify-between">
<view>
{{item.title}}
</view>
</view>
<view class="dateContent rangenumber-content flex">
<view class="rangenumber-input">
<input class="m-input" type="number" clearable v-model="result[item.minName || (item.key + 'Min')]"
:placeholder="item.minPlaceholder || '最小值'"
@blur="numberInputBlur(item)"></input>
</view>
<text>-</text>
<view class="rangenumber-input">
<input class="m-input" type="number" clearable v-model="result[item.maxName || (item.key + 'Max')]"
:placeholder="item.maxPlaceholder || '最大值'"
@blur="numberInputBlur(item)"></input>
</view>
</view>
</view>
<!-- 单输入框 -->
<view v-if="item.type === 'singleinput'">
<view class="drawer-list-title flex justify-between">
<view>
{{item.title}}
</view>
</view>
<view class="dateContent">
<view>
<input class="m-input" clearable v-model="result[item.key]"
:placeholder="item.placeholder || '请输入关键字'" />
</view>
</view>
</view>
</block>
</scroll-view>
<view class="filter-content-footer flex justify-center">
<!-- #ifdef APP-PLUS-->
<view v-if="showBackButton" class="filter-content-footer-item" :style="{color: '#ccc', 'border': '1rpx solid #ccc'}"
@tap="closeDrawer()">
<text>返回</text>
</view>
<!-- #endif -->
<view class="filter-content-footer-item" :style="{color, 'border': `1rpx solid ${color}`}"
@tap="resetClick">
<text>重置</text>
</view>
<view class="filter-content-footer-item" :style="{'background': color}" @tap="sureClick">
<text>确认</text>
</view>
</view>
</uni-drawer>
<mx-date-picker :show="showPicker" :color="color" :type="dateType" :value="dateValue" :show-tips="true"
:show-seconds="true" @confirm="onSelected" @cancel="onSelected" />
</view>
</template>
<script>
/***
* 筛选组件当前支持多选单选
* item.type (custom 单选多选rangetime 时间范围带时分秒range 时间范围不带时分秒rangenumber 数字范围)
* item.isMutiple 是否支持多选
* 筛选后返回格式{"listName1":[value,value](多选),"listName2":"value"单选,...}
* rangenumber形式-可能为["",1][1,""]表示只有一个最大值或最小值
***/
import uniDrawer from '@/components/uni-drawer/uni-drawer.vue';
import MxDatePicker from "@/components/mx-datepicker/mx-datepicker.vue";
export default {
props: {
list: {
required: true,
type: Array,
default () {
return [];
},
},
color: {
type: String,
default: '#4D7BFE',
},
defaultValue: { //若有默认值则触发sureClick
type: Object,
default () {
return {}
},
},
showBackButton: {
type: Boolean,
default: false,
}
},
watch: {
list: {
handler(val) {
this.menuList = JSON.parse(JSON.stringify(val));
this.resetResult();
this.defaultValueFun();
},
deep: true // 可以深度检测到 obj 对象的属性值的变化
}
},
components: {
uniDrawer,
MxDatePicker
},
beforeCreate() {
Object.isEmpty = (object, except = []) => {
if (!object) {
return false;
}
for (let key in object) {
if (except && except.includes(key)) {
continue;
}
if (object.hasOwnProperty(key)) {
return false;
}
}
return true;
};
Date.prototype.Format = function(fmt) { //author: meizz
var o = {
"M+": this.getMonth() + 1, //月份
"d+": this.getDate(), //日
"h+": this.getHours(), //小时
"m+": this.getMinutes(), //分
"s+": this.getSeconds(), //秒
"q+": Math.floor((this.getMonth() + 3) / 3), //季度
"S": this.getMilliseconds() //毫秒
};
if (/(y+)/.test(fmt)) fmt = fmt.replace(RegExp.$1, (this.getFullYear() + "").substr(4 - RegExp.$1
.length));
for (var k in o)
if (new RegExp("(" + k + ")").test(fmt)) fmt = fmt.replace(RegExp.$1, (RegExp.$1.length == 1) ? (o[
k]) : (("00" + o[
k]).substr(("" + o[k]).length)));
return fmt;
};
String.prototype.replaceAll = function(oldValue, newValue) { return this.toString().replace(new RegExp(oldValue, 'gm'), newValue); }
},
created() {
this.menuList = JSON.parse(JSON.stringify(this.list));
this.resetResult();
uni.getSystemInfo({
success: (res) => {
let windowHeight = res.windowHeight;
// #ifdef H5
if (!(this.$IsWeixin || this.$IsAlipay || this.$IsCloudPay)) {
let thirdApp = getApp().globalData.options?.thirdApp;
if (thirdApp && thirdApp.hideNavBar) {
// 第三方App使用App原生导航栏
} else {
this.fixTop = (res.statusBarHeight || 0) + 'px';
}
}
windowHeight = window.innerHeight || document.documentElement.clientHeight || document.body
.clientHeight || res.windowHeight;
// #endif
this.drawerHeight = (windowHeight - uni.upx2px(120)) + 'px';
// uni.showModal({
// content: `model: ${res.model}`,
// })
}
});
},
mounted() {
this.defaultValueFun();
},
computed: {
},
data() {
return {
menuList: [],
visibleDrawer: false,
menuKey: 1,
showLenght: 6,
drawerHeight: '500px',
selectDetailList: [],
result: {},
showPicker: false,
dateType: 'rangetime',
dateValue: '',
fixTop: '0px'
};
},
methods: {
defaultValueFun() {
//如果有默认值则赋值后调用sureClick通知父组件更新
if (!Object.isEmpty(this.defaultValue)) {
const value = this.defaultValue;
const list = JSON.parse(JSON.stringify(this.menuList));
for (let key in value) {
for (let i = 0; i < list.length; i++) {
if (list[i].key === key) {
if (list[i].type === 'custom') {
list[i].detailList.map((item, index) => {
if (Array.isArray(value[key]) && value[key].indexOf(item.value) > -1) {
item.isSelected = true;
} else if (value[key] == item.value) {
item.isSelected = true;
}
return item;
})
continue;
}
if (list[i].type === 'range' || list[i].type === 'rangetime' || list[i].type === 'rangenumber' && Array.isArray(value[key]) && value[key].length === 2) {
this.result[key] = value[key];
this.result[list[i].minName || (list[i].key + 'Min')] = value[key][0];
this.result[list[i].maxName || (list[i].key + 'Max')] = value[key][1];
continue;
}
if (list[i].type === 'date' || list[i].type === 'singleinput' && value[key]) {
this.result[key] = value[key];
continue;
}
}
}
}
if (this.defaultRefeshTimer) {
clearTimeout(this.defaultRefesh·Timer);
}
this.defaultRefeshTimer = setTimeout(() => {
console.log('筛选默认值触发')
this.menuList = list;
this.sureClick();
}, 200);
}
},
resetResult() {
this.result = this.commonResultObj();
},
commonResultObj() {
let obj = {};
this.menuList.map((item) => {
switch(item.type) {
case "custom":
item.isMutiple ? obj[item.key] = [] : obj[item.key] = '';
item.detailList.forEach(dListItem => {
dListItem.isSelected = dListItem.isSelected || false;
});
break;
case 'range':
case 'rangetime':
case 'rangenumber':
this.result[item.key] = [];
this.result[item.minName || (item.key + 'Min')] = '';
this.result[item.maxName || (item.key + 'Max')] = '';
break;
default:
obj[item.key] = '';
}
})
return obj;
},
//筛选项选中或取消
itemTap(index, list, key, isMutiple) {
if (isMutiple == true) {
list[index].isSelected = !list[index].isSelected;
if (list[index].isSelected) {
this.result[key].push(list[index].value);
} else {
list[index].isSelected = false;
var idx = this.result[key].indexOf(list[index].value);
this.result[key].splice(idx, 1);
}
} else {
this.result[key] = list[index].isSelected ? '' : list[index].value;
for (let i = 0; i < list.length; i++) {
if (index == i && !list[i].isSelected) {
list[i].isSelected = true
} else {
list[i].isSelected = false
}
}
}
// #ifdef H5 || APP-PLUS
this.$forceUpdate();
// #endif
},
sureClick() {
this.menuList.forEach(menu => {
let list = menu.detailList || [];
if (menu.type == 'custom' && list.length > 0) {
let selectedValueList = [];
list.forEach(item => {
if (item.isSelected) {
selectedValueList.push(item.value);
}
});
if (menu.isMutiple == true) {
this.result[menu.key] = selectedValueList;
} else {
this.result[menu.key] = selectedValueList[0] || '';
}
}
});
let str_result = {};
let hasChoose = false;
for (let key in this.result) {
if (typeof this.result[key] == 'object') {
str_result[key] = this.result[key].join(',');
if (!hasChoose) {
hasChoose = this.result[key].join(',') !== '' ? true : false;
}
} else {
str_result[key] = this.result[key];
if (!hasChoose) {
hasChoose = this.result[key] !== '' ? true : false;
}
}
}
this.$emit("result", {
'str_result': str_result,
'result': this.result,
'hasChoose': hasChoose,
'visibleDrawer': false
});
},
resetClick() {
this.minNumber = '';
this.maxNumber = '';
for (let key in this.result) {
if (typeof this.result[key] === 'object') {
this.result[key] = [];
} else {
this.result[key] = '';
}
}
for (let i = 0; i < this.menuList.length; i++) {
if (this.menuList[i].type === 'custom') {
for (let j = 0; j < this.menuList[i].detailList.length; j++) {
this.menuList[i].detailList[j].isSelected = false;
}
}
}
// #ifdef H5 || APP-PLUS
this.$forceUpdate();
// #endif
},
closeDrawer() {
this.visibleDrawer = false;
// #ifdef APP-PLUS
this.$emit("result", {
type: 1,
});
// #endif
},
showMore(index) {
this.menuList[index].showMoreList = !this.menuList[index].showMoreList;
++this.menuKey;
// #ifdef H5 || APP-NVUE
this.$forceUpdate();
// #endif
},
onShowDatePicker(type, key, item) { //显示
this.dateType = type;
this.dateValue = this.result[key] || '';
this.showPicker = true;
this.tempKey = key;
this.item = item;
},
onSelected(e, key) { //选择
this.showPicker = false;
if (e) {
this.result[this.tempKey] = e.value;
if (e.value && e.value.length && this.item && this.item.type !== 'date') {
let item = this.item;
this.result[item.minName || (item.key + 'Min')] = e.value[0].replaceAll('/', '-');
this.result[item.maxName || (item.key + 'Max')] = e.value[1].replaceAll('/', '-');
}
//选择的值
console.log('value => ' + e.value);
//原始的Date对象
console.log('date => ' + e.date);
}
},
numberInputBlur(item) {
let minNumber = this.result[item.minName || (item.key + 'Min')];
let maxNumber = this.result[item.maxName || (item.key + 'Max')];
if (minNumber != '' && maxNumber != '' && parseFloat(minNumber) > parseFloat(maxNumber)) {
let temp = minNumber;
this.result[item.minName || (item.key + 'Min')] = maxNumber;
this.result[item.maxName || (item.key + 'Max')] = temp;
}
this.result[item.key] = [];
this.result[item.key].push(minNumber && parseFloat(minNumber));
this.result[item.key].push(maxNumber && parseFloat(maxNumber));
}
}
}
</script>
<style lang="scss" scoped>
.flex {
display: flex;
}
.justify-between {
justify-content: space-between;
}
view,
scroll-view,
swiper,
button,
input,
textarea,
label,
navigator,
image {
box-sizing: border-box;
}
/* 筛选样式 */
.drawer-list {
padding: 0 20rpx;
font-size: 26rpx;
}
input {
font-size: 26rpx;
}
.drawer-list .drawer-list-title {
font-size: 34rpx;
font-weight: 400;
line-height: 48rpx;
margin: 38rpx 0 18rpx;
color: rgba(34, 34, 34, 1);
}
.drawer-list .drawer-list-title>text {
font-size: 26rpx;
color: #666666;
}
.drawer-list .draer-list-con>text {
background: rgba(93, 92, 254, 0.1);
border-radius: 28px;
color: #666666;
font-size: 28rpx;
padding: 10rpx 28rpx;
margin: 10rpx 10rpx 10rpx 0;
display: inline-block;
}
.filter-content-footer-item {
flex: 1;
height: 72rpx;
line-height: 72rpx;
text-align: center;
border-radius: 8rpx;
margin: 14rpx;
color: #FFFFFF;
}
.picker {
z-index: 99999 !important;
}
.dateContent {
&>view {
background: rgba(244, 244, 244, 1);
border-radius: 8rpx;
width: 100%;
height: 64rpx;
line-height: 64rpx;
margin-bottom: 12rpx;
padding: 0 12rpx;
}
}
.rangenumber-content {
&>text {
display: inline-block;
width: 10%;
text-align: center;
height: 64rpx;
line-height: 64rpx;
}
.rangenumber-input {
width: 45%;
display: inline-block;
padding: 0 12rpx;
}
}
.m-input {
height: 64rpx;
line-height: 64rpx;
}
::v-deep .picker {
z-index: 999;
}
.icon-guanbi {
position: fixed;
top: 40rpx;
right: 40rpx;
z-index: 1000;
}
</style>