|
@@ -1,753 +0,0 @@
|
|
|
-<!--
|
|
|
-时间刻度尺组件 (TimeScale)
|
|
|
-
|
|
|
-功能:
|
|
|
-- 显示水平时间轴,包含月份标记和小刻度
|
|
|
-- 支持用户滑动选择时间
|
|
|
-- 每两天显示一个小刻度
|
|
|
-- 中间固定竖线,显示当前选中的时间
|
|
|
-- 时间格式:YYYY-MM-DD
|
|
|
-
|
|
|
-Props:
|
|
|
-- currentDate: String - 当前选中的时间 (YYYY-MM-DD格式)
|
|
|
-
|
|
|
-Events:
|
|
|
-- timeChange: (date: String) - 时间变化时触发,返回YYYY-MM-DD格式的日期
|
|
|
-
|
|
|
-使用示例:
|
|
|
-<time-scale
|
|
|
- :current-date="selectedDate"
|
|
|
- @time-change="handleTimeChange"
|
|
|
-></time-scale>
|
|
|
--->
|
|
|
-
|
|
|
-<template>
|
|
|
- <view class="time-scale-container">
|
|
|
- <view class="time-scale-scroll">
|
|
|
- <scroll-view
|
|
|
- class="time-scale-wrapper"
|
|
|
- scroll-x
|
|
|
- :scroll-left="scrollLeft"
|
|
|
- scroll-with-animation
|
|
|
- @scroll="handleScroll"
|
|
|
- @scrolltolower="handleScrollToLower"
|
|
|
- @scrolltoupper="handleScrollToUpper"
|
|
|
- ref="scrollViewRef"
|
|
|
- >
|
|
|
- <view class="time-scale">
|
|
|
- <!-- 月份标签 -->
|
|
|
- <view class="month-labels">
|
|
|
- <view
|
|
|
- class="month-label"
|
|
|
- v-for="(month, index) in monthLabels"
|
|
|
- :key="`month-${index}`"
|
|
|
- :style="{ left: month.left + 'rpx' }"
|
|
|
- >
|
|
|
- {{ month.label }}
|
|
|
- </view>
|
|
|
- </view>
|
|
|
-
|
|
|
- <!-- 时间轴 -->
|
|
|
- <view class="timeline">
|
|
|
- <!-- 月份大点 -->
|
|
|
- <view
|
|
|
- class="month-dot"
|
|
|
- v-for="(month, index) in monthLabels"
|
|
|
- :key="`dot-${index}`"
|
|
|
- :style="{ left: month.left + 'rpx' }"
|
|
|
- ></view>
|
|
|
-
|
|
|
- <!-- 小刻度 -->
|
|
|
- <view
|
|
|
- class="tick-mark"
|
|
|
- v-for="(tick, index) in tickMarks"
|
|
|
- :key="`tick-${index}`"
|
|
|
- :style="{ left: tick.left + 'rpx' }"
|
|
|
- ></view>
|
|
|
- </view>
|
|
|
-
|
|
|
-
|
|
|
- </view>
|
|
|
- </scroll-view>
|
|
|
-
|
|
|
- <!-- 中间竖线 -->
|
|
|
- <view class="center-line"></view>
|
|
|
- </view>
|
|
|
-
|
|
|
- <!-- 当前时间显示 -->
|
|
|
- <view class="current-time" v-if="currentTime">
|
|
|
- {{ formatDisplayTime(currentTime) }}
|
|
|
- </view>
|
|
|
- </view>
|
|
|
-</template>
|
|
|
-
|
|
|
-<script setup>
|
|
|
-import { ref, computed, onMounted, watch, nextTick } from 'vue'
|
|
|
-
|
|
|
-const props = defineProps({
|
|
|
- // 当前选中的时间
|
|
|
- currentDate: {
|
|
|
- type: String,
|
|
|
- default: ''
|
|
|
- }
|
|
|
-})
|
|
|
-
|
|
|
-const emit = defineEmits(['timeChange'])
|
|
|
-
|
|
|
-// 响应式数据
|
|
|
-const currentTime = ref('')
|
|
|
-let scrollTimer = null // 防抖定时器
|
|
|
-const scrollViewRef = ref(null) // 滚动视图引用
|
|
|
-const scrollLeft = ref(0) // 滚动位置
|
|
|
-
|
|
|
-// 计算属性:生成月份标签
|
|
|
-const monthLabels = computed(() => {
|
|
|
- const labels = []
|
|
|
- const now = new Date()
|
|
|
- const currentYear = now.getFullYear()
|
|
|
- const currentMonth = now.getMonth()
|
|
|
-
|
|
|
- // 从当前月份往前一年的月份,从右到左排列
|
|
|
- for (let i = 0; i <= 11; i++) {
|
|
|
- const date = new Date(currentYear, currentMonth - i, 1)
|
|
|
- const year = date.getFullYear()
|
|
|
- const month = date.getMonth() + 1
|
|
|
-
|
|
|
- labels.push({
|
|
|
- label: `${month}月`,
|
|
|
- year: year,
|
|
|
- month: month,
|
|
|
- left: (11 - i) * 200 + 100, // 从右到左排列,当前月份在最右边
|
|
|
- monthOffset: i // 添加月份偏移信息
|
|
|
- })
|
|
|
- }
|
|
|
-
|
|
|
- return labels
|
|
|
-})
|
|
|
-
|
|
|
-// 计算属性:生成小刻度
|
|
|
-const tickMarks = computed(() => {
|
|
|
- const ticks = []
|
|
|
- const now = new Date()
|
|
|
- const currentYear = now.getFullYear()
|
|
|
- const currentMonth = now.getMonth()
|
|
|
-
|
|
|
- // 从当前月份往前一年的刻度,从右到左排列
|
|
|
- for (let monthOffset = 0; monthOffset <= 11; monthOffset++) {
|
|
|
- const date = new Date(currentYear, currentMonth - monthOffset, 1)
|
|
|
- const year = date.getFullYear()
|
|
|
- const month = date.getMonth() + 1
|
|
|
- const daysInMonth = new Date(year, month, 0).getDate()
|
|
|
-
|
|
|
- // 每隔一天一个刻度,从第2天开始
|
|
|
- for (let day = 2; day <= daysInMonth; day++) {
|
|
|
- const monthLeft = (11 - monthOffset) * 200 + 100
|
|
|
- const dayOffset = ((day - 1) / daysInMonth) * 200
|
|
|
- ticks.push({
|
|
|
- left: monthLeft + dayOffset,
|
|
|
- date: `${year}-${month.toString().padStart(2, '0')}-${day.toString().padStart(2, '0')}`
|
|
|
- })
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- return ticks
|
|
|
-})
|
|
|
-
|
|
|
-// 格式化显示时间
|
|
|
-const formatDisplayTime = (dateStr) => {
|
|
|
- const [year, month, day] = dateStr.split('-')
|
|
|
- return `${year}年${month}月${day}日`
|
|
|
-}
|
|
|
-
|
|
|
-// 根据时间计算位置
|
|
|
-const calculatePositionByDate = (dateStr) => {
|
|
|
- const [year, month, day] = dateStr.split('-').map(Number)
|
|
|
- const now = new Date()
|
|
|
- const currentYear = now.getFullYear()
|
|
|
- const currentMonth = now.getMonth()
|
|
|
-
|
|
|
- // 计算月份偏移(从当前月份往前)- 使用与月份标签相同的逻辑
|
|
|
- // 月份标签: new Date(currentYear, currentMonth - i, 1) 其中 i 从 0 到 11
|
|
|
- // 所以对于目标日期,我们需要找到对应的 i 值
|
|
|
- let monthOffset = -1
|
|
|
- for (let i = 0; i <= 11; i++) {
|
|
|
- const testDate = new Date(currentYear, currentMonth - i, 1)
|
|
|
- if (testDate.getFullYear() === year && testDate.getMonth() + 1 === month) {
|
|
|
- monthOffset = i
|
|
|
- break
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- if (monthOffset === -1 || monthOffset > 11) return 0
|
|
|
-
|
|
|
- // 计算月份位置(从右到左)
|
|
|
- const monthLeft = (11 - monthOffset) * 200 + 100
|
|
|
-
|
|
|
- // 计算在月份内的位置,使用与calculateDateByPosition相同的计算逻辑
|
|
|
- const daysInMonth = new Date(year, month, 0).getDate()
|
|
|
- const dayRatio = (day - 1) / daysInMonth
|
|
|
- const dayOffset = dayRatio * 200
|
|
|
-
|
|
|
- return monthLeft + dayOffset
|
|
|
-}
|
|
|
-
|
|
|
-// 根据位置计算时间
|
|
|
-const calculateDateByPosition = (left) => {
|
|
|
- // 计算月份索引(从右到左)
|
|
|
- const monthIndex = Math.floor((left - 100) / 200)
|
|
|
- const monthOffset = 11 - monthIndex
|
|
|
-
|
|
|
- if (monthOffset < 0 || monthOffset > 11) return ''
|
|
|
-
|
|
|
- const now = new Date()
|
|
|
- const currentYear = now.getFullYear()
|
|
|
- const currentMonth = now.getMonth()
|
|
|
-
|
|
|
- // 计算目标月份 - 使用与月份标签完全相同的逻辑
|
|
|
- // 月份标签: new Date(currentYear, currentMonth - i, 1) 其中 i 从 0 到 11
|
|
|
- // 这里 monthOffset 对应月份标签中的 i
|
|
|
- const targetDate = new Date(currentYear, currentMonth - monthOffset, 1)
|
|
|
- const year = targetDate.getFullYear()
|
|
|
- const month = targetDate.getMonth() + 1
|
|
|
- const daysInMonth = new Date(year, month, 0).getDate()
|
|
|
-
|
|
|
- // 计算在月份内的位置
|
|
|
- const monthLeft = monthIndex * 200 + 100
|
|
|
- const dayOffset = left - monthLeft
|
|
|
-
|
|
|
- // 确保dayOffset在有效范围内
|
|
|
- if (dayOffset < 0 || dayOffset > 200) return ''
|
|
|
-
|
|
|
- // 计算日期比例(0-1),使用更精确的计算方法
|
|
|
- const dayRatio = dayOffset / 200
|
|
|
-
|
|
|
- // 计算日期(1-31),使用四舍五入而不是向下取整
|
|
|
- let day = Math.round(dayRatio * daysInMonth) + 1
|
|
|
-
|
|
|
- // 确保日期在有效范围内
|
|
|
- day = Math.max(1, Math.min(daysInMonth, day))
|
|
|
-
|
|
|
- return `${year}-${month.toString().padStart(2, '0')}-${day.toString().padStart(2, '0')}`
|
|
|
-}
|
|
|
-
|
|
|
-// 调试函数:验证时间计算
|
|
|
-const debugTimeCalculation = (left) => {
|
|
|
- const date = calculateDateByPosition(left)
|
|
|
- const position = calculatePositionByDate(date)
|
|
|
- const difference = Math.abs(left - position)
|
|
|
- console.log(`位置: ${left}, 计算时间: ${date}, 反向计算位置: ${position}, 误差: ${difference}`)
|
|
|
- return date
|
|
|
-}
|
|
|
-
|
|
|
-// 精确调试函数:测试特定位置
|
|
|
-const preciseDebug = (left) => {
|
|
|
- const date = calculateDateByPosition(left)
|
|
|
- const [year, month, day] = date.split('-').map(Number)
|
|
|
- const monthIndex = Math.floor((left - 100) / 200)
|
|
|
- const monthOffset = 11 - monthIndex
|
|
|
- const monthLeft = monthIndex * 200 + 100
|
|
|
- const dayOffset = left - monthLeft
|
|
|
- const dayRatio = dayOffset / 200
|
|
|
- const daysInMonth = new Date(year, month, 0).getDate()
|
|
|
-
|
|
|
- console.log(`=== 精确调试 ===`)
|
|
|
- console.log(`输入位置: ${left}`)
|
|
|
- console.log(`月份索引: ${monthIndex}, 月份偏移: ${monthOffset}`)
|
|
|
- console.log(`月份左边界: ${monthLeft}, 日期偏移: ${dayOffset}`)
|
|
|
- console.log(`日期比例: ${dayRatio}, 月份天数: ${daysInMonth}`)
|
|
|
- console.log(`计算日期: ${day}, 最终时间: ${date}`)
|
|
|
-
|
|
|
- // 添加反向验证
|
|
|
- const reversePosition = calculatePositionByDate(date)
|
|
|
- const reverseDate = calculateDateByPosition(reversePosition)
|
|
|
- console.log(`反向验证: 位置 ${reversePosition} -> 时间 ${reverseDate}`)
|
|
|
- console.log(`一致性检查: ${date === reverseDate ? '✅' : '❌'}`)
|
|
|
-
|
|
|
- return date
|
|
|
-}
|
|
|
-
|
|
|
-// 时间差分析函数
|
|
|
-const analyzeTimeDifference = (left) => {
|
|
|
- console.log(`=== 时间差分析 ===`)
|
|
|
- console.log(`分析位置: ${left}`)
|
|
|
-
|
|
|
- // 计算当前时间
|
|
|
- const date = calculateDateByPosition(left)
|
|
|
- console.log(`计算时间: ${date}`)
|
|
|
-
|
|
|
- // 计算反向位置
|
|
|
- const reversePosition = calculatePositionByDate(date)
|
|
|
- console.log(`反向位置: ${reversePosition}`)
|
|
|
-
|
|
|
- // 计算位置差
|
|
|
- const positionDiff = Math.abs(left - reversePosition)
|
|
|
- console.log(`位置差: ${positionDiff}`)
|
|
|
-
|
|
|
- // 分析可能的原因
|
|
|
- if (positionDiff > 5) {
|
|
|
- console.log(`⚠️ 位置差较大,可能原因:`)
|
|
|
- console.log(`1. 日期计算精度问题`)
|
|
|
- console.log(`2. 月份边界处理问题`)
|
|
|
- console.log(`3. 四舍五入误差`)
|
|
|
- }
|
|
|
-
|
|
|
- return { date, reversePosition, positionDiff }
|
|
|
-}
|
|
|
-
|
|
|
-// 处理滚动事件
|
|
|
-const handleScroll = (e) => {
|
|
|
- // 清除之前的定时器
|
|
|
- if (scrollTimer) {
|
|
|
- clearTimeout(scrollTimer)
|
|
|
- }
|
|
|
-
|
|
|
- // 设置新的定时器,防抖处理
|
|
|
- scrollTimer = setTimeout(() => {
|
|
|
- const scrollLeft = e.detail.scrollLeft
|
|
|
- const containerWidth = 750 // 假设容器宽度为750rpx
|
|
|
- const centerPosition = containerWidth / 2
|
|
|
-
|
|
|
- // 计算当前中心位置对应的时间
|
|
|
- const absoluteLeft = scrollLeft + centerPosition
|
|
|
- const date = calculateDateByPosition(absoluteLeft)
|
|
|
-
|
|
|
- if (date && date !== currentTime.value) {
|
|
|
- currentTime.value = date
|
|
|
- emit('timeChange', date)
|
|
|
- console.log('当前选中时间:', date) // 打印格式为YYYY-MM-DD
|
|
|
-
|
|
|
- // 详细调试信息
|
|
|
- console.log(`滚动位置: ${scrollLeft}, 中心位置: ${centerPosition}, 绝对位置: ${absoluteLeft}`)
|
|
|
- preciseDebug(absoluteLeft)
|
|
|
-
|
|
|
- // 时间差分析
|
|
|
- analyzeTimeDifference(absoluteLeft)
|
|
|
- }
|
|
|
- }, 50) // 减少防抖时间,提高响应性
|
|
|
-}
|
|
|
-
|
|
|
-// 处理滚动到底部
|
|
|
-const handleScrollToLower = () => {
|
|
|
- console.log('滚动到底部')
|
|
|
-}
|
|
|
-
|
|
|
-// 处理滚动到顶部
|
|
|
-const handleScrollToUpper = () => {
|
|
|
- console.log('滚动到顶部')
|
|
|
-}
|
|
|
-
|
|
|
-// 监听props变化
|
|
|
-watch(() => props.currentDate, (newDate) => {
|
|
|
- if (newDate && newDate !== currentTime.value) {
|
|
|
- currentTime.value = newDate
|
|
|
- }
|
|
|
-}, { immediate: true })
|
|
|
-
|
|
|
-// 验证月份标签和位置计算的对应关系
|
|
|
-const validateMonthPositionMapping = () => {
|
|
|
- console.log('=== 月份位置映射验证 ===')
|
|
|
-
|
|
|
- monthLabels.value.forEach((label, index) => {
|
|
|
- const expectedDate = `${label.year}-${label.month.toString().padStart(2, '0')}-01`
|
|
|
- const calculatedPosition = calculatePositionByDate(expectedDate)
|
|
|
- const reverseDate = calculateDateByPosition(calculatedPosition)
|
|
|
-
|
|
|
- console.log(`月份${index + 1}: ${label.label}`)
|
|
|
- console.log(` 标签位置: ${label.left}`)
|
|
|
- console.log(` 期望日期: ${expectedDate}`)
|
|
|
- console.log(` 计算位置: ${calculatedPosition}`)
|
|
|
- console.log(` 反向日期: ${reverseDate}`)
|
|
|
- console.log(` 位置一致: ${Math.abs(label.left - calculatedPosition) < 1 ? '✅' : '❌'}`)
|
|
|
- console.log(` 日期一致: ${expectedDate === reverseDate ? '✅' : '❌'}`)
|
|
|
- console.log('---')
|
|
|
- })
|
|
|
-}
|
|
|
-
|
|
|
-// 验证月份标签和位置计算的一致性
|
|
|
-const validateMonthConsistency = () => {
|
|
|
- console.log('=== 月份一致性验证 ===')
|
|
|
- monthLabels.value.forEach((label, index) => {
|
|
|
- const expectedDate = `${label.year}-${label.month.toString().padStart(2, '0')}-01`
|
|
|
- const calculatedPosition = calculatePositionByDate(expectedDate)
|
|
|
- const reverseDate = calculateDateByPosition(calculatedPosition)
|
|
|
- const difference = Math.abs(label.left - calculatedPosition)
|
|
|
-
|
|
|
- console.log(`月份${index + 1}: ${label.label} (${expectedDate})`)
|
|
|
- console.log(` 标签位置: ${label.left}, 计算位置: ${calculatedPosition}, 误差: ${difference}`)
|
|
|
- console.log(` 反向验证: ${reverseDate} vs ${expectedDate}`)
|
|
|
- console.log(` 一致性: ${reverseDate === expectedDate ? '✅' : '❌'}`)
|
|
|
- console.log('---')
|
|
|
- })
|
|
|
-}
|
|
|
-
|
|
|
-// 验证月份标签位置
|
|
|
-const validateMonthLabels = () => {
|
|
|
- console.log('=== 月份标签验证 ===')
|
|
|
- monthLabels.value.forEach((label, index) => {
|
|
|
- const expectedDate = `${label.year}-${label.month.toString().padStart(2, '0')}-01`
|
|
|
- const calculatedPosition = calculatePositionByDate(expectedDate)
|
|
|
- const difference = Math.abs(label.left - calculatedPosition)
|
|
|
- console.log(`月份${index + 1}: ${label.label} (${expectedDate}) -> 标签位置: ${label.left}, 计算位置: ${calculatedPosition}, 误差: ${difference}`)
|
|
|
- })
|
|
|
-}
|
|
|
-
|
|
|
-// 测试函数:验证时间计算逻辑
|
|
|
-const testTimeCalculation = () => {
|
|
|
- console.log('=== 时间计算测试 ===')
|
|
|
-
|
|
|
- // 先验证月份位置映射
|
|
|
- validateMonthPositionMapping()
|
|
|
-
|
|
|
- // 再验证月份一致性
|
|
|
- validateMonthConsistency()
|
|
|
-
|
|
|
- // 再验证月份标签
|
|
|
- validateMonthLabels()
|
|
|
-
|
|
|
- // 测试几个关键位置(从右到左)
|
|
|
- const testPositions = [
|
|
|
- 2300, // 最右边(当前月份第一天)
|
|
|
- 2100, // 当前月份中间
|
|
|
- 1900, // 上个月第一天
|
|
|
- 1700, // 上上个月第一天
|
|
|
- 1500, // 三个月前第一天
|
|
|
- 1300, // 四个月前第一天
|
|
|
- 1100, // 五个月前第一天
|
|
|
- 900, // 六个月前第一天
|
|
|
- 700, // 七个月前第一天
|
|
|
- 500, // 八个月前第一天
|
|
|
- 300, // 九个月前第一天
|
|
|
- 100 // 最左边(一年前)
|
|
|
- ]
|
|
|
-
|
|
|
- testPositions.forEach((pos, index) => {
|
|
|
- const date = calculateDateByPosition(pos)
|
|
|
- const reversePos = calculatePositionByDate(date)
|
|
|
- const difference = Math.abs(pos - reversePos)
|
|
|
- console.log(`测试${index + 1}: 位置 ${pos} -> 时间 ${date} -> 反向位置 ${reversePos}, 误差: ${difference}`)
|
|
|
-
|
|
|
- // 如果误差太大,输出详细调试信息
|
|
|
- if (difference > 10) {
|
|
|
- console.log('--- 误差过大,详细调试 ---')
|
|
|
- preciseDebug(pos)
|
|
|
- }
|
|
|
- })
|
|
|
-}
|
|
|
-
|
|
|
-// 显示月份对比信息
|
|
|
-const showMonthComparison = () => {
|
|
|
- console.log('=== 月份对比信息 ===')
|
|
|
-
|
|
|
- const now = new Date()
|
|
|
- const currentYear = now.getFullYear()
|
|
|
- const currentMonth = now.getMonth() + 1
|
|
|
-
|
|
|
- console.log(`当前时间: ${currentYear}年${currentMonth}月`)
|
|
|
- console.log(`月份标签数量: ${monthLabels.value.length}`)
|
|
|
-
|
|
|
- // 显示所有月份标签
|
|
|
- monthLabels.value.forEach((label, index) => {
|
|
|
- console.log(`标签${index + 1}: ${label.label} (${label.year}-${label.month}) 位置: ${label.left}`)
|
|
|
-
|
|
|
- // 计算该月份第一天对应的位置
|
|
|
- const firstDayDate = `${label.year}-${label.month.toString().padStart(2, '0')}-01`
|
|
|
- const calculatedPosition = calculatePositionByDate(firstDayDate)
|
|
|
- const reverseDate = calculateDateByPosition(calculatedPosition)
|
|
|
-
|
|
|
- console.log(` 计算位置: ${calculatedPosition}, 反向日期: ${reverseDate}`)
|
|
|
- console.log(` 位置一致: ${Math.abs(label.left - calculatedPosition) < 1 ? '✅' : '❌'}`)
|
|
|
- console.log(` 日期一致: ${firstDayDate === reverseDate ? '✅' : '❌'}`)
|
|
|
- })
|
|
|
-}
|
|
|
-
|
|
|
-// 显示当前月份信息
|
|
|
-const showCurrentMonthInfo = () => {
|
|
|
- const now = new Date()
|
|
|
- const currentYear = now.getFullYear()
|
|
|
- const currentMonth = now.getMonth() + 1
|
|
|
-
|
|
|
- console.log('=== 当前月份信息 ===')
|
|
|
- console.log(`当前年份: ${currentYear}, 当前月份: ${currentMonth}`)
|
|
|
- console.log(`月份标签数量: ${monthLabels.value.length}`)
|
|
|
-
|
|
|
- // 显示所有月份标签
|
|
|
- monthLabels.value.forEach((label, index) => {
|
|
|
- console.log(`标签${index + 1}: ${label.label} (${label.year}-${label.month}) 位置: ${label.left}`)
|
|
|
- })
|
|
|
-
|
|
|
- return { year: currentYear, month: currentMonth }
|
|
|
-}
|
|
|
-
|
|
|
-// 显示当前日期信息
|
|
|
-const showCurrentDateInfo = () => {
|
|
|
- const now = new Date()
|
|
|
- const currentYear = now.getFullYear()
|
|
|
- const currentMonth = now.getMonth() + 1
|
|
|
- const currentDay = now.getDate()
|
|
|
-
|
|
|
- console.log('=== 当前日期信息 ===')
|
|
|
- console.log(`当前日期: ${currentYear}-${currentMonth.toString().padStart(2, '0')}-${currentDay.toString().padStart(2, '0')}`)
|
|
|
- console.log(`当前年份: ${currentYear}, 当前月份: ${currentMonth}, 当前日期: ${currentDay}`)
|
|
|
-
|
|
|
- // 计算当前日期在时间轴上的位置
|
|
|
- const currentDateStr = `${currentYear}-${currentMonth.toString().padStart(2, '0')}-${currentDay.toString().padStart(2, '0')}`
|
|
|
- const currentPosition = calculatePositionByDate(currentDateStr)
|
|
|
- console.log(`当前日期在时间轴上的位置: ${currentPosition}`)
|
|
|
-
|
|
|
- return currentDateStr
|
|
|
-}
|
|
|
-
|
|
|
-// 测试每天刻度的准确性
|
|
|
-const testDailyTicks = () => {
|
|
|
- console.log('=== 每天刻度测试 ===')
|
|
|
-
|
|
|
- const now = new Date()
|
|
|
- const currentYear = now.getFullYear()
|
|
|
- const currentMonth = now.getMonth()
|
|
|
-
|
|
|
- // 测试当前月份的几个关键日期
|
|
|
- const testDays = [1, 5, 10, 15, 20, 25, 30]
|
|
|
-
|
|
|
- testDays.forEach(day => {
|
|
|
- const testDate = new Date(currentYear, currentMonth, day)
|
|
|
- const year = testDate.getFullYear()
|
|
|
- const month = testDate.getMonth() + 1
|
|
|
- const daysInMonth = new Date(year, month, 0).getDate()
|
|
|
-
|
|
|
- // 只测试有效的日期
|
|
|
- if (day <= daysInMonth) {
|
|
|
- const dateStr = `${year}-${month.toString().padStart(2, '0')}-${day.toString().padStart(2, '0')}`
|
|
|
- const position = calculatePositionByDate(dateStr)
|
|
|
- const reverseDate = calculateDateByPosition(position)
|
|
|
- const isAccurate = dateStr === reverseDate
|
|
|
-
|
|
|
- console.log(`日期: ${dateStr} -> 位置: ${position} -> 反向: ${reverseDate} ${isAccurate ? '✅' : '❌'}`)
|
|
|
- }
|
|
|
- })
|
|
|
-}
|
|
|
-
|
|
|
-// 简单测试:验证月份对应关系
|
|
|
-const simpleTest = () => {
|
|
|
- console.log('=== 简单测试 ===')
|
|
|
-
|
|
|
- // 测试当前月份
|
|
|
- const now = new Date()
|
|
|
- const currentYear = now.getFullYear()
|
|
|
- const currentMonth = now.getMonth() + 1
|
|
|
- const currentDate = `${currentYear}-${currentMonth.toString().padStart(2, '0')}-01`
|
|
|
-
|
|
|
- console.log(`当前月份: ${currentMonth}月`)
|
|
|
- console.log(`当前日期: ${currentDate}`)
|
|
|
-
|
|
|
- // 计算位置
|
|
|
- const position = calculatePositionByDate(currentDate)
|
|
|
- console.log(`计算位置: ${position}`)
|
|
|
-
|
|
|
- // 反向计算时间
|
|
|
- const reverseDate = calculateDateByPosition(position)
|
|
|
- console.log(`反向计算: ${reverseDate}`)
|
|
|
-
|
|
|
- // 验证一致性
|
|
|
- const isConsistent = currentDate === reverseDate
|
|
|
- console.log(`一致性: ${isConsistent ? '✅' : '❌'}`)
|
|
|
-
|
|
|
- return isConsistent
|
|
|
-}
|
|
|
-
|
|
|
-// 测试3个月差问题
|
|
|
-const testThreeMonthDifference = () => {
|
|
|
- console.log('=== 3个月差问题测试 ===')
|
|
|
-
|
|
|
- const now = new Date()
|
|
|
- const currentYear = now.getFullYear()
|
|
|
- const currentMonth = now.getMonth() + 1
|
|
|
-
|
|
|
- console.log(`当前时间: ${currentYear}年${currentMonth}月`)
|
|
|
-
|
|
|
- // 测试当前月份的位置
|
|
|
- const currentMonthDate = `${currentYear}-${currentMonth.toString().padStart(2, '0')}-01`
|
|
|
- const currentPosition = calculatePositionByDate(currentMonthDate)
|
|
|
- const currentReverseDate = calculateDateByPosition(currentPosition)
|
|
|
-
|
|
|
- console.log(`当前月份: ${currentMonthDate}`)
|
|
|
- console.log(`计算位置: ${currentPosition}`)
|
|
|
- console.log(`反向计算: ${currentReverseDate}`)
|
|
|
- console.log(`当前月份一致性: ${currentMonthDate === currentReverseDate ? '✅' : '❌'}`)
|
|
|
-
|
|
|
- // 测试3个月前的月份
|
|
|
- const threeMonthsAgo = new Date(currentYear, currentMonth - 4, 1) // 减4是因为getMonth()返回0-11
|
|
|
- const threeMonthsAgoYear = threeMonthsAgo.getFullYear()
|
|
|
- const threeMonthsAgoMonth = threeMonthsAgo.getMonth() + 1
|
|
|
- const threeMonthsAgoDate = `${threeMonthsAgoYear}-${threeMonthsAgoMonth.toString().padStart(2, '0')}-01`
|
|
|
-
|
|
|
- const threeMonthsPosition = calculatePositionByDate(threeMonthsAgoDate)
|
|
|
- const threeMonthsReverseDate = calculateDateByPosition(threeMonthsPosition)
|
|
|
-
|
|
|
- console.log(`3个月前: ${threeMonthsAgoDate}`)
|
|
|
- console.log(`计算位置: ${threeMonthsPosition}`)
|
|
|
- console.log(`反向计算: ${threeMonthsReverseDate}`)
|
|
|
- console.log(`3个月前一致性: ${threeMonthsAgoDate === threeMonthsReverseDate ? '✅' : '❌'}`)
|
|
|
-
|
|
|
- // 检查月份标签
|
|
|
- console.log('月份标签检查:')
|
|
|
- monthLabels.value.forEach((label, index) => {
|
|
|
- if (label.year === threeMonthsAgoYear && label.month === threeMonthsAgoMonth) {
|
|
|
- console.log(`找到3个月前标签: ${label.label} 位置: ${label.left}`)
|
|
|
- console.log(`位置差: ${Math.abs(label.left - threeMonthsPosition)}`)
|
|
|
- }
|
|
|
- })
|
|
|
-}
|
|
|
-
|
|
|
-// 组件挂载后初始化
|
|
|
-onMounted(() => {
|
|
|
- // 运行简单测试
|
|
|
- simpleTest()
|
|
|
-
|
|
|
- // 测试每天刻度
|
|
|
- testDailyTicks()
|
|
|
-
|
|
|
- // 测试3个月差问题
|
|
|
- testThreeMonthDifference()
|
|
|
-
|
|
|
- // 显示月份对比信息
|
|
|
- showMonthComparison()
|
|
|
-
|
|
|
- // 显示当前月份信息
|
|
|
- showCurrentMonthInfo()
|
|
|
-
|
|
|
- // 显示当前日期信息
|
|
|
- showCurrentDateInfo()
|
|
|
-
|
|
|
- // 运行测试
|
|
|
- testTimeCalculation()
|
|
|
-
|
|
|
- // 如果没有传入当前日期,使用今天
|
|
|
- if (!props.currentDate) {
|
|
|
- const today = new Date()
|
|
|
- const year = today.getFullYear()
|
|
|
- const month = (today.getMonth() + 1).toString().padStart(2, '0')
|
|
|
- const day = today.getDate().toString().padStart(2, '0')
|
|
|
- const todayStr = `${year}-${month}-${day}`
|
|
|
-
|
|
|
- currentTime.value = todayStr
|
|
|
- emit('timeChange', todayStr)
|
|
|
-
|
|
|
- // 设置默认滚动到最右边(当前日期位置)
|
|
|
- nextTick(() => {
|
|
|
- // 计算需要滚动的距离,让最右边(当前月份)显示在屏幕中间
|
|
|
- // 总宽度2400rpx,屏幕宽度750rpx,要让最右边显示在中间
|
|
|
- scrollLeft.value = 2400 - 750
|
|
|
- })
|
|
|
- } else {
|
|
|
- // 如果有传入日期,初始化时间
|
|
|
- currentTime.value = props.currentDate
|
|
|
-
|
|
|
- // 设置默认滚动到传入日期位置
|
|
|
- nextTick(() => {
|
|
|
- const targetPosition = calculatePositionByDate(props.currentDate)
|
|
|
- // 计算需要滚动的距离,让目标日期显示在屏幕中间
|
|
|
- scrollLeft.value = targetPosition - 375
|
|
|
- })
|
|
|
- }
|
|
|
-})
|
|
|
-</script>
|
|
|
-
|
|
|
-<style lang="scss" scoped>
|
|
|
-.time-scale-container {
|
|
|
- width: 100%;
|
|
|
- position: relative;
|
|
|
- margin-bottom: 20rpx;
|
|
|
- padding: 0 20rpx;
|
|
|
-}
|
|
|
-
|
|
|
-.time-scale-scroll {
|
|
|
- position: relative;
|
|
|
- width: 100%;
|
|
|
- height: 120rpx;
|
|
|
-}
|
|
|
-
|
|
|
-.time-scale-wrapper {
|
|
|
- width: 100%;
|
|
|
- height: 100%;
|
|
|
- white-space: nowrap;
|
|
|
-}
|
|
|
-
|
|
|
-.time-scale {
|
|
|
- display: inline-block;
|
|
|
- min-width: 2400rpx; // 12个月 * 200rpx
|
|
|
- height: 100%;
|
|
|
- position: relative;
|
|
|
- padding: 0 375rpx; // 左右各留一半屏幕宽度,确保最左和最右都在中间
|
|
|
-}
|
|
|
-
|
|
|
-.month-labels {
|
|
|
- position: relative;
|
|
|
- height: 40rpx;
|
|
|
-}
|
|
|
-
|
|
|
-.month-label {
|
|
|
- position: absolute;
|
|
|
- top: 0;
|
|
|
- transform: translateX(-50%);
|
|
|
- font-size: 24rpx;
|
|
|
- color: #777777;
|
|
|
- font-weight: 500;
|
|
|
-}
|
|
|
-
|
|
|
-.timeline {
|
|
|
- position: relative;
|
|
|
- height: 80rpx;
|
|
|
- margin-top: 20rpx;
|
|
|
-
|
|
|
- &::before {
|
|
|
- content: '';
|
|
|
- position: absolute;
|
|
|
- top: 50%;
|
|
|
- left: 0;
|
|
|
- right: 0;
|
|
|
- height: 2rpx;
|
|
|
- background: rgba(136, 136, 136, 0.1);
|
|
|
- transform: translateY(-50%);
|
|
|
- }
|
|
|
-}
|
|
|
-
|
|
|
-.month-dot {
|
|
|
- position: absolute;
|
|
|
- top: 50%;
|
|
|
- width: 14rpx;
|
|
|
- height: 14rpx;
|
|
|
- background: #777777;
|
|
|
- border-radius: 50%;
|
|
|
- transform: translate(-50%, -50%);
|
|
|
- z-index: 5;
|
|
|
-}
|
|
|
-
|
|
|
-.tick-mark {
|
|
|
- position: absolute;
|
|
|
- top: 50%;
|
|
|
- width: 2rpx;
|
|
|
- height: 8rpx;
|
|
|
- background: rgba(136, 136, 136, 0.3);
|
|
|
- transform: translate(-50%, -50%);
|
|
|
-}
|
|
|
-
|
|
|
-.center-line {
|
|
|
- position: absolute;
|
|
|
- left: 50%;
|
|
|
- top: 0;
|
|
|
- bottom: 0;
|
|
|
- width: 2rpx;
|
|
|
- background: #2199F8;
|
|
|
- z-index: 15;
|
|
|
- transform: translateX(-50%);
|
|
|
- pointer-events: none;
|
|
|
-}
|
|
|
-
|
|
|
-.current-time {
|
|
|
- text-align: center;
|
|
|
- margin-top: 16rpx;
|
|
|
- font-size: 28rpx;
|
|
|
- color: #2199F8;
|
|
|
- font-weight: 500;
|
|
|
-}
|
|
|
-</style>
|