123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753 |
- <!--
- 时间刻度尺组件 (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>
|