多层组件嵌套
<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.value
choose.value = modelV.value
let time = choose.value ? new Date(choose.value) : new Date()
currentDataVal.value = Math.floor(time.getFullYear() / 10) * 10
futureDataVal.value = currentDataVal.value * 1 + 9
zqBodyPopupRef.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.value
choose.value = modelV.value
let time = choose.value ? new Date(choose.value) : new Date()
currentDataVal.value = Math.floor(time.getFullYear() / 10) * 10
futureDataVal.value = currentDataVal.value * 1 + 9
zqBodyPopupRef.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-model
modelValue: {
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');
// 日期 和 年 都包含 between
if (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>