Files
YGChatCS/src/components/Calender/example.vue
2026-01-07 12:12:01 +08:00

315 lines
7.9 KiB
Vue
Raw 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="calendar-example">
<!-- 页面标题 -->
<view class="page-header">
<text class="page-title">日历组件使用示例</text>
</view>
<!-- 触发器区域 -->
<view class="trigger-section">
<view class="date-input" @tap="openCalendar">
<view class="input-content">
<text class="input-label">选择日期</text>
<text class="input-value" v-if="selectedDate">{{ selectedDate }}</text>
<text class="input-placeholder" v-else>请选择日期</text>
</view>
<uni-icons type="calendar" size="20" color="#1890ff"></uni-icons>
</view>
<!-- 范围选择示例 -->
<view class="date-input" @tap="openRangeCalendar">
<view class="input-content">
<text class="input-label">选择日期范围</text>
<text class="input-value" v-if="selectedRange.start && selectedRange.end">
{{ selectedRange.start }} {{ selectedRange.end }}
</text>
<text class="input-placeholder" v-else>请选择日期范围</text>
</view>
<uni-icons type="calendar" size="20" color="#1890ff"></uni-icons>
</view>
<!-- 价格区间选择示例 -->
<view class="date-input" @tap="openPriceRangeCalendar">
<view class="input-content">
<text class="input-label">选择有价格的日期范围</text>
<text class="input-value" v-if="selectedRange.start && selectedRange.end">
{{ selectedRange.start }} {{ selectedRange.end }}
</text>
<text class="input-placeholder" v-else>请选择价格区间仅含有价夜晚</text>
</view>
<uni-icons type="calendar" size="20" color="#1890ff"></uni-icons>
</view>
</view>
<!-- 结果显示区域 -->
<view class="result-section" v-if="selectedDate || (selectedRange.start && selectedRange.end)">
<text class="result-title">选择结果</text>
<view class="result-item" v-if="selectedDate">
<text class="result-label">单选日期</text>
<text class="result-value">{{ selectedDate }}</text>
<text class="result-value" v-if="selectedDatePrice"> ¥{{ selectedDatePrice }} </text>
</view>
<view class="result-item" v-if="selectedRange.start && selectedRange.end">
<text class="result-label">日期范围</text>
<text class="result-value">{{ selectedRange.start }} {{ selectedRange.end }}</text>
<text class="result-days">{{ rangeDays }}</text>
<text class="result-value" v-if="selectedRangeTotal"> 总价¥{{ selectedRangeTotal }} </text>
</view>
</view>
<!-- 日历组件 - 单选模式 -->
<Calendar
:visible="calendarVisible"
:price-data="priceData"
mode="single"
:default-value="selectedDate"
@close="handleCalendarClose"
@select="handleDateSelect"
/>
<!-- 日历组件 - 范围选择模式 -->
<Calendar
:visible="rangeCalendarVisible"
:price-data="priceData"
mode="range"
:default-value="[selectedRange.start, selectedRange.end]"
@close="handleRangeCalendarClose"
@range-select="handleRangeSelect"
/>
<!-- 日历组件 - 价格区间选择模式必须有价格的夜晚 -->
<Calendar
:visible="priceRangeCalendarVisible"
:price-data="priceData"
mode="range"
:range-require-price="true"
:default-value="[selectedRange.start, selectedRange.end]"
@close="handleRangeCalendarClose"
@range-select="handlePriceRangeSelect"
/>
</view>
</template>
<script setup>
import { ref, computed } from 'vue'
import Calendar from './index.vue'
// 响应式数据
const calendarVisible = ref(false)
const rangeCalendarVisible = ref(false)
const priceRangeCalendarVisible = ref(false)
const selectedDate = ref('')
const selectedDatePrice = ref(null)
const selectedRange = ref({
start: '',
end: ''
})
const selectedRangeTotal = ref(null)
// 模拟价格数据
const priceData = ref({
'2024-01-15': 299,
'2024-01-16': 399,
'2024-01-17': 199,
'2024-01-18': 299,
'2024-01-19': 399,
'2024-01-20': 499,
'2024-01-21': 599,
'2024-01-22': 299,
'2024-01-23': 199,
'2024-01-24': 299,
'2024-01-25': 399,
'2024-01-26': 299,
'2024-01-27': 199,
'2024-01-28': 299
})
// 计算属性
const rangeDays = computed(() => {
if (!selectedRange.value.start || !selectedRange.value.end) return 0
const start = new Date(selectedRange.value.start)
const end = new Date(selectedRange.value.end)
const diffTime = Math.abs(end - start)
return Math.ceil(diffTime / (1000 * 60 * 60 * 24)) + 1
})
// 方法定义
// 打开单选日历
const openCalendar = () => {
calendarVisible.value = true
}
// 打开范围选择日历
const openRangeCalendar = () => {
rangeCalendarVisible.value = true
}
// 打开价格区间选择器(必须以价格为准)
const openPriceRangeCalendar = () => {
priceRangeCalendarVisible.value = true
}
// 处理单选日历关闭
const handleCalendarClose = () => {
calendarVisible.value = false
}
// 处理范围选择日历关闭
const handleRangeCalendarClose = () => {
rangeCalendarVisible.value = false
}
// 处理日期选择
const handleDateSelect = (data) => {
selectedDate.value = data.date
selectedDatePrice.value = (data.price !== undefined && data.price !== null && data.price !== '-') ? data.price : null
calendarVisible.value = false
console.log('选择的日期:', data)
}
// 处理范围选择
const handleRangeSelect = (data) => {
selectedRange.value = {
start: data.startDate,
end: data.endDate
}
if (data.dateRange && Array.isArray(data.dateRange)) {
const total = data.dateRange.reduce((sum, d) => {
const p = d.price
return sum + (typeof p === 'number' ? p : 0)
}, 0)
selectedRangeTotal.value = total || null
} else {
selectedRangeTotal.value = null
}
rangeCalendarVisible.value = false
console.log('选择的日期范围:', data)
}
// 处理价格区间选择
const handlePriceRangeSelect = (data) => {
selectedRange.value = {
start: data.startDate,
end: data.endDate
}
if (data.dateRange && Array.isArray(data.dateRange)) {
const total = data.dateRange.reduce((sum, d) => {
const p = d.price
return sum + (typeof p === 'number' ? p : 0)
}, 0)
selectedRangeTotal.value = total || null
} else {
selectedRangeTotal.value = null
}
priceRangeCalendarVisible.value = false
console.log('价格区间选择:', data)
}
</script>
<style lang="scss" scoped>
.calendar-example {
padding: 20px;
background-color: #f5f5f5;
min-height: 100vh;
}
.page-header {
margin-bottom: 30px;
text-align: center;
}
.page-title {
font-size: 24px;
font-weight: 600;
color: #262626;
}
.trigger-section {
display: flex;
flex-direction: column;
gap: 16px;
margin-bottom: 30px;
}
.date-input {
display: flex;
align-items: center;
justify-content: space-between;
padding: 16px;
background-color: #ffffff;
border-radius: 8px;
border: 1px solid #d9d9d9;
transition: border-color 0.2s;
&:active {
border-color: #1890ff;
}
}
.input-content {
flex: 1;
display: flex;
flex-direction: column;
gap: 4px;
}
.input-label {
font-size: 14px;
color: #8c8c8c;
font-weight: 500;
}
.input-value {
font-size: 16px;
color: #262626;
font-weight: 500;
}
.input-placeholder {
font-size: 16px;
color: #bfbfbf;
}
.result-section {
padding: 20px;
background-color: #ffffff;
border-radius: 8px;
margin-bottom: 20px;
}
.result-title {
font-size: 16px;
font-weight: 600;
color: #262626;
margin-bottom: 12px;
}
.result-item {
display: flex;
align-items: center;
margin-bottom: 8px;
&:last-child {
margin-bottom: 0;
}
}
.result-label {
font-size: 14px;
color: #8c8c8c;
margin-right: 8px;
min-width: 80px;
}
.result-value {
font-size: 14px;
color: #1890ff;
font-weight: 500;
}
.result-days {
font-size: 12px;
color: #52c41a;
margin-left: 8px;
}
</style>