多层组件嵌套
<template><view class=""><view class="zq-imitate-input" @click="toggleContent"><text v-if="valueStr.length > 0">{{ valueStr }}</text><text v-else>{{ datePlaceholder }}</text><text v-if="valueStr.length > 0" class="zq-imitate-input-clearable" @click.stop="onClearable"><uni-icons type="clear" size="22" color="rgb(192, 196, 204)"></uni-icons></text></view><zqBodyPopup ref="zqBodyPopupRef" :key="'time-popup-'" mode="bottom" :overlayOpacity="0"><!-- 关闭按钮 --><uni-icons type="closeempty" size="20" class="upper-close-icon" @click="closeUpper"></uni-icons><YearTimeItem ref="YearTimeItemRef" :yearValue="yearValue" @onChangeSelect="onChangeYearItem"></YearTimeItem><view class="zq-button-group"><button>重置</button><button type="primary" @click='changeValueBtn'>确定</button></view></zqBodyPopup></view>
</template><script lang="ts" setup>
import { ref, reactive, watch, onMounted, computed } from "vue";
import zqBodyPopup from '../zq-body-popup/zq-body-popup.vue'
import YearTimeItem from './zq-select-year.vue'
import { isArray } from "../../utils/tool";const zqBodyPopupRef = ref();
const YearTimeItemRef = ref('')
const open = () => {zqBodyPopupRef.value.open();
};const emits = defineEmits(['update:modelValue', 'yeartimePickermodelValue'])const props = defineProps({quick: {type: Object,default: () => {return {}},},// 标记的日期markDays: {type: Array,default: () => {return []; //例如["2023-05-01", "2023-05-03", "2023-04-13"]}},modelValue: {type: Object,default: () => {return {}},},allValue: {type: Object,default: () => {return {}},},
})
// const localdata = ref([{
// value: 'LE',
// text: '小于等于',
// },
// {
// value: 'GE',
// text: '大于等于',
// },
// {
// value: 'EQ',
// text: '等于',
// },
// ])
const modelV = ref([]);
const popupShow = ref('')
// const zqBodyPopupRef = ref()
const dates = ref([]) // 当前月的日期数据
const currentDataVal = ref('')
const futureDataVal = ref('')
const choose = ref('')
// const valueStr = ref('')
const showUpper = ref(false);
const placeholderStr = ref('请选择年份');
// yeartimeValue.value.operator=
// modelV.value.yearhangeTime = props.quick.modelValue
// modelV.value.operator = props.quick.gl ? props.quick.gl : "GE"
const yearValue = ref('')
const toggleContent = () => {// console.log(modelV.value, '===');yearValue.value = modelV.valuechoose.value = modelV.valuelet time = choose.value ? new Date(choose.value) : new Date()currentDataVal.value = Math.floor(time.getFullYear() / 10) * 10futureDataVal.value = currentDataVal.value * 1 + 9zqBodyPopupRef.value.open();// uni.hideKeyboard();
}
// computed
const valueStr = computed(() => {console.log(props.allValue, '---props.allValue');if (props.allValue.operator === 'BETWEEN') {return props.allValue.rangeValue.join(' 至 ')} else {return props.allValue.dateValue}// if (modelV.value) {// return modelV.value?.join('-')// } else {// return ''// }
})
const datePlaceholder = computed(() => {if (props.allValue.operator === 'BETWEEN') {return `开始年份 - 结束年份`} else {return '选择年份';}
})
// watch
watch(() => props.modelValue,(newV) => {console.log(newV,props.modelValue, '---newV');// if (newV && Object.keys(newV).length > 0) {if (isArray(newV)) {modelV.value = newV} else {console.error('zq-pagelist time 类型 value(modelValue) 值,传入应为 Array 类型')}// }},{deep: true,immediate: true,}
)
// 标记日期
const isMarkDay = (y, key) => {console.log(y, key, '当前遍历的日期项', y, key);let flag = false;// console.log('传递过来需要标记的日期项', this.markDays);props.markDays.forEach(item => {let dy = `${y}`if (item == dy) {flag = true}})return flag;
}
// // 点击回调
const selectOne = (i, event) => {let date = `${i + event}`;let selectD = new Date(date).getTime();let curTime = new Date().getTime();choose.value = date}
watch(modelV.value, (newV) => {emits('yeartimePickermodelValue', newV);
}, {deep: true,immediate: true,
})const changeMonth = (type) => {if (type == 'pre') {currentDataVal.value = currentDataVal.value - 10;futureDataVal.value = futureDataVal.value - 10;} else {currentDataVal.value = currentDataVal.value + 10;futureDataVal.value = futureDataVal.value + 10;}
}
// 点击确定返回值
const changeValueBtn = () => {modelV.value.yearhangeTime = tempYear.value// console.log(modelV.value,'---modelV.value');const temp = ['']// if(modelV.value.operator == 'LE') {temp[0] = modelV.value.yearhangeTime// }emits('update:modelValue', temp);zqBodyPopupRef.value.close()}
//
const tempYear = ref('')
const onChangeYearItem = (e) => {console.log(e, '---onChangeYearItem');tempYear.value = e// modelV.value.yearhangeTime = e// emits('yeartimePickermodelValue', modelV.value);}
const closeUpper = () => {zqBodyPopupRef.value.close();
}
// imitate-input中的clearable属性
const onClearable = () => {emits('update:modelValue', ['']);
}
</script><style scoped lang="scss">
.year-select {:deep(.uni-select) {background-color: var(--UI-BG-5);}
}.zq-quicks-checkbox-popup-box {position: fixed;background-color: #fff;z-index: 999;right: 0;bottom: 0;margin-top: 10upx;// width: 100%;// width: 100vh !important;.checkbox-popup-con {background-color: rgba(0, 0, 0, 0.4);border-radius: 20upx 20upx 0 0;margin-bottom: 10upx;padding: 20upx;box-sizing: border-box;:deep(.checkbox__inner) {display: none !important;}:deep(.checklist-box) {width: 50% !important;display: flex;align-items: center;height: 3vh;margin: 0 !important;padding: 0 !important;}}}.uni-date-editor--x .uni-date__icon-clear[data-v-9802168a] {padding-right: 3px;display: flex;align-items: center;cursor: pointer;
}.uni-icons[data-v-d31e1c47] {font-family: uniicons;text-decoration: none;text-align: center
}.long-popup {::deep .uni-scroll-view-content {transform: none !important;}
}.calendar-wrapper {// width: 100vw;// color: #bbb7b7;font-size: 28rpx;text-align: center;background-color: #fff;padding-bottom: 10rpx;.header {display: flex;align-items: center;justify-content: center;// height: 88rpx;color: #42464A;font-size: 32rpx;font-weight: bold;.pre,.next {color: #4d7df9;font-size: 28rpx;font-weight: normal;padding: 8rpx 15rpx;border-radius: 10rpx;// border: 2rpx solid #dcdfe6;}.pre {margin-right: 30rpx;}.next {margin-left: 30rpx;}}
}.choose {background-color: #4d7df9;color: #fff;
}@mixin flex {/* #ifndef APP-NVUE */display: flex;/* #endif */flex-direction: row;
}::v-deep.is-input-border[data-v-09fd5285] {border: none;
}.popup-content {@include flex;align-items: center;justify-content: center;background-color: #fff;
}.content {position: relative;overflow: hidden;transition: height 0.4s ease;.days {transition: top 0.3s;display: flex;align-items: center;flex-wrap: wrap;position: relative;.item {position: relative;display: block;height: 120rpx;line-height: 120rpx;width: calc(100% / 4);.day {font-style: normal;display: inline-block;vertical-align: middle;width: 60rpx;height: 60rpx;line-height: 60rpx;// overflow: hidden;// border-radius: 60rpx;&.choose {background-color: #4d7df9;color: #fff;}}}}
}.upper-close-icon {position: absolute;right: 10upx;top: 15px;z-index: 90;
}
</style>
<template><view class=""><view class="zq-imitate-input" @click="toggleContent"><text v-if="valueStr.length > 0">{{ valueStr }}</text><text v-else>{{ datePlaceholder }}</text><text v-if="valueStr.length > 0" class="zq-imitate-input-clearable" @click.stop="onClearable"><uni-icons type="clear" size="22" color="rgb(192, 196, 204)"></uni-icons></text></view><zqBodyPopup ref="zqBodyPopupRef" :key="'time-popup-'" mode="bottom" :overlayOpacity="0">{{ yearValue }}<!-- 关闭按钮 --><uni-icons type="closeempty" size="20" class="upper-close-icon" @click="closeUpper"></uni-icons><YearTimeItem ref="YearTimeItemRef" :yearValue="yearValue" @onChangeSelect="onChangeYearItem"></YearTimeItem><view class="zq-button-group"><button>重置</button><button type="primary" @click='changeValueBtn'>确定</button></view></zqBodyPopup></view>
</template><script lang="ts" setup>
import { ref, reactive, watch, onMounted, computed } from "vue";
import zqBodyPopup from '../../../../zq-body-popup/zq-body-popup.vue'
import YearTimeItem from '../../../../zq-input-year/zq-select-year.vue'
import { isArray } from "../../../../../utils/tool";const zqBodyPopupRef = ref();
const YearTimeItemRef = ref('')
const open = () => {zqBodyPopupRef.value.open();
};const emits = defineEmits(['update:modelValue', 'yeartimePickermodelValue'])const props = defineProps({quick: {type: Object,default: () => {return {}},},// 标记的日期markDays: {type: Array,default: () => {return []; //例如["2023-05-01", "2023-05-03", "2023-04-13"]}},modelValue: {type: Object,default: () => {return {}},},allValue: {type: Object,default: () => {return {}},},
})
// const localdata = ref([{
// value: 'LE',
// text: '小于等于',
// },
// {
// value: 'GE',
// text: '大于等于',
// },
// {
// value: 'EQ',
// text: '等于',
// },
// ])
const modelV = ref([]);
const popupShow = ref('')
// const zqBodyPopupRef = ref()
const dates = ref([]) // 当前月的日期数据
const currentDataVal = ref('')
const futureDataVal = ref('')
const choose = ref('')
// const valueStr = ref('')
const showUpper = ref(false);
const placeholderStr = ref('请选择年份');
// yeartimeValue.value.operator=
// modelV.value.yearhangeTime = props.quick.modelValue
// modelV.value.operator = props.quick.gl ? props.quick.gl : "GE"
const yearValue = ref('')
const toggleContent = () => {// console.log(modelV.value, '===');yearValue.value = modelV.valuechoose.value = modelV.valuelet time = choose.value ? new Date(choose.value) : new Date()currentDataVal.value = Math.floor(time.getFullYear() / 10) * 10futureDataVal.value = currentDataVal.value * 1 + 9zqBodyPopupRef.value.open();// uni.hideKeyboard();
}
// computed
const valueStr = computed(() => {console.log(props.allValue, '---props.allValue');if (props.allValue.operator === 'BETWEEN') {return props.allValue.rangeValue.join(' 至 ')} else {return props.allValue.dateValue}// if (modelV.value) {// return modelV.value?.join('-')// } else {// return ''// }
})
const datePlaceholder = computed(() => {if (props.allValue.operator === 'BETWEEN') {return `开始年份 - 结束年份`} else {return '选择年份';}
})
// watch
watch(() => props.modelValue,(newV) => {console.log(newV,props.modelValue, '---newV');// if (newV && Object.keys(newV).length > 0) {if (isArray(newV)) {modelV.value = newV} else {console.error('zq-pagelist time 类型 value(modelValue) 值,传入应为 Array 类型')}// }},{deep: true,immediate: true,}
)
// 标记日期
const isMarkDay = (y, key) => {console.log(y, key, '当前遍历的日期项', y, key);let flag = false;// console.log('传递过来需要标记的日期项', this.markDays);props.markDays.forEach(item => {let dy = `${y}`if (item == dy) {flag = true}})return flag;
}
// // 点击回调
const selectOne = (i, event) => {let date = `${i + event}`;let selectD = new Date(date).getTime();let curTime = new Date().getTime();choose.value = date}
watch(modelV.value, (newV) => {emits('yeartimePickermodelValue', newV);
}, {deep: true,immediate: true,
})const changeMonth = (type) => {if (type == 'pre') {currentDataVal.value = currentDataVal.value - 10;futureDataVal.value = futureDataVal.value - 10;} else {currentDataVal.value = currentDataVal.value + 10;futureDataVal.value = futureDataVal.value + 10;}
}
// 点击确定返回值
const changeValueBtn = () => {modelV.value.yearhangeTime = tempYear.value// console.log(modelV.value,'---modelV.value');const temp = ['']// if(modelV.value.operator == 'LE') {temp[0] = modelV.value.yearhangeTime// }emits('update:modelValue', temp);zqBodyPopupRef.value.close()}
//
const tempYear = ref('')
const onChangeYearItem = (e) => {console.log(e, '---onChangeYearItem');tempYear.value = e// modelV.value.yearhangeTime = e// emits('yeartimePickermodelValue', modelV.value);}
const closeUpper = () => {zqBodyPopupRef.value.close();
}
// imitate-input中的clearable属性
const onClearable = () => {emits('update:modelValue', ['']);
}
</script><style scoped lang="scss">
.year-select {:deep(.uni-select) {background-color: var(--UI-BG-5);}
}.zq-quicks-checkbox-popup-box {position: fixed;background-color: #fff;z-index: 999;right: 0;bottom: 0;margin-top: 10upx;// width: 100%;// width: 100vh !important;.checkbox-popup-con {background-color: rgba(0, 0, 0, 0.4);border-radius: 20upx 20upx 0 0;margin-bottom: 10upx;padding: 20upx;box-sizing: border-box;:deep(.checkbox__inner) {display: none !important;}:deep(.checklist-box) {width: 50% !important;display: flex;align-items: center;height: 3vh;margin: 0 !important;padding: 0 !important;}}}.uni-date-editor--x .uni-date__icon-clear[data-v-9802168a] {padding-right: 3px;display: flex;align-items: center;cursor: pointer;
}.uni-icons[data-v-d31e1c47] {font-family: uniicons;text-decoration: none;text-align: center
}.long-popup {::deep .uni-scroll-view-content {transform: none !important;}
}.calendar-wrapper {// width: 100vw;// color: #bbb7b7;font-size: 28rpx;text-align: center;background-color: #fff;padding-bottom: 10rpx;.header {display: flex;align-items: center;justify-content: center;// height: 88rpx;color: #42464A;font-size: 32rpx;font-weight: bold;.pre,.next {color: #4d7df9;font-size: 28rpx;font-weight: normal;padding: 8rpx 15rpx;border-radius: 10rpx;// border: 2rpx solid #dcdfe6;}.pre {margin-right: 30rpx;}.next {margin-left: 30rpx;}}
}.choose {background-color: #4d7df9;color: #fff;
}@mixin flex {/* #ifndef APP-NVUE */display: flex;/* #endif */flex-direction: row;
}::v-deep.is-input-border[data-v-09fd5285] {border: none;
}.popup-content {@include flex;align-items: center;justify-content: center;background-color: #fff;
}.content {position: relative;overflow: hidden;transition: height 0.4s ease;.days {transition: top 0.3s;display: flex;align-items: center;flex-wrap: wrap;position: relative;.item {position: relative;display: block;height: 120rpx;line-height: 120rpx;width: calc(100% / 4);.day {font-style: normal;display: inline-block;vertical-align: middle;width: 60rpx;height: 60rpx;line-height: 60rpx;// overflow: hidden;// border-radius: 60rpx;&.choose {background-color: #4d7df9;color: #fff;}}}}
}.upper-close-icon {position: absolute;right: 10upx;top: 15px;z-index: 90;
}
</style>
<template><view class="time-box"><uni-data-select v-model="modelValue.operator" :localdata="curOperator" :clear="false" class="operator-select" /><dateTpl v-if="comb.type === 'date'" :modelValue="modelValue.value" @update:modelValue="changeValue":allValue="modelValue" :quick="comb" class="time-content-box" /><yearTpl v-else-if="comb.type === 'year'" :modelValue="modelValue.value" @update:modelValue="changeValue":allValue="modelValue" :quick="comb" class="time-content-box" /></view>
</template><script setup>
import { ref, watch, getCurrentInstance } from 'vue'
import dateTpl from './date-time/datetimePicker.vue'
import yearTpl from './year/yearTimePickchange.vue'
const operatorData_Base = [{value: 'LE',text: '小于等于',},{value: 'GE',text: '大于等于',},{value: 'EQ',text: '等于',},{value: 'BETWEEN',text: '介于',}
];const props = defineProps({//v-modelmodelValue: {type: Object,default: function () {return {}},},comb: {type: Object,default: function () {return {}},},
});
const emits = defineEmits(['update:modelValue'])const curOperator = ref([]); // 下拉框可选项
const init = () => {console.log(props, '---props.comb.operatorOptions');// 日期 和 年 都包含 betweenif (props.comb.operatorOptions) {curOperator.value = props.comb.operatorOptions;} else {// 可配置 选择项curOperator.value = operatorData_Base.slice();}// 父传子,数据回显if (props.modelValue.dateValue) {props.modelValue.value[0] = props.modelValue.dateValue}// modelV.value = Object.assign({}, props.modelValue)
}
init();
const changeValue = (valueArr) => {let tempObj = Object.assign({}, props.modelValue);if (props.modelValue.operator === 'BETWEEN') {tempObj.rangeValue = valueArr;} else {tempObj.dateValue = valueArr[0]}tempObj.value = valueArr;emits('update:modelValue', tempObj);
}</script><style lang="scss" scoped>
.time-box {display: flex;.operator-select {max-width: 30%;margin: 0 3%;}.time-content-box {width: 61%;margin-right: 3%;}:deep .uni-select {background-color: #fff;}
}
</style>