Просмотр исходного кода

refactor(date): 提取日期工具到共享模块

- 将重复的日期处理函数提取到 src/utils/date.ts
- 统一管理周开始/结束日期计算逻辑
- 共享 daysInMonth、formatDisplayDate 等工具函数
- 所有健康详情页面引入并使用新的日期工具集
- 删除各页面中原本重复定义的日期函数实现
- 添加 weekDayIndex 工具函数用于周内日期索引计算
mcbaiyun 2 месяцев назад
Родитель
Сommit
cb03f0106d

+ 5 - 38
src/pages/health/details/blood-glucose.vue

@@ -97,6 +97,7 @@ import uCharts from '@qiun/ucharts'
 import CustomNav from '@/components/custom-nav.vue'
 import TabBar from '@/components/tab-bar.vue'
 import ScaleRuler from '@/components/scale-ruler.vue'
+import { getWeekStart, getWeekEnd, getWeekNumber, formatDisplayDate, formatPickerDate, daysInMonth, weekDayIndex } from '@/utils/date'
 
 type RecordItem = { id: string; date: string; value: number; type: string }
 
@@ -129,12 +130,7 @@ function getCanvasSize(): Promise<{ width: number; height: number }> {
   });
 }
 
-function formatPickerDate(d: Date) {
-  const y = d.getFullYear()
-  const m = String(d.getMonth() + 1).padStart(2, '0')
-  const day = String(d.getDate()).padStart(2, '0')
-  return `${y}-${m}-${day}`
-}
+// 使用共享日期工具 (src/utils/date.ts)
 
 const displayYear = computed(() => current.value.getFullYear())
 const displayMonth = computed(() => current.value.getMonth() + 1)
@@ -186,32 +182,7 @@ function generateMockRecords(d: Date): RecordItem[] {
 }
 
 // 获取指定日期所在周的开始日期(星期一)
-function getWeekStart(date: Date): Date {
-  const d = new Date(date)
-  d.setHours(0, 0, 0, 0)
-  const day = d.getDay()
-  const diff = day === 0 ? -6 : 1 - day
-  d.setDate(d.getDate() + diff)
-  d.setHours(0, 0, 0, 0)
-  return d
-}
-
-// 获取指定日期所在周的结束日期(星期日)
-function getWeekEnd(date: Date): Date {
-  const d = getWeekStart(date)
-  d.setDate(d.getDate() + 6)
-  d.setHours(0, 0, 0, 0)
-  return d
-}
-
-// 获取指定日期所在周的周数(一年中的第几周)
-function getWeekNumber(date: Date): number {
-  const d = new Date(date)
-  d.setHours(0, 0, 0, 0)
-  d.setDate(d.getDate() + 4 - (d.getDay() || 7))
-  const yearStart = new Date(d.getFullYear(), 0, 1)
-  return Math.ceil(((d.getTime() - yearStart.getTime()) / 86400000 + 1) / 7)
-}
+// 使用共享日期工具 (src/utils/date.ts)
 
 // 将 records 聚合为每天一个点(取最新记录)
 function aggregateDaily(recordsArr: RecordItem[], year: number, month: number) {
@@ -232,9 +203,7 @@ function aggregateDaily(recordsArr: RecordItem[], year: number, month: number) {
   return map
 }
 
-function formatDisplayDate(d: Date) {
-  return `${d.getFullYear()}-${String(d.getMonth() + 1).padStart(2, '0')}-${String(d.getDate()).padStart(2, '0')}`
-}
+// 使用 formatDisplayDate 从 src/utils/date.ts
 
 const averageGlucose = computed(() => {
   if (records.value.length === 0) return '--'
@@ -242,9 +211,7 @@ const averageGlucose = computed(() => {
   return (sum / records.value.length).toFixed(1)
 })
 
-function daysInMonth(year: number, month: number) {
-  return new Date(year, month + 1, 0).getDate()
-}
+// 使用 daysInMonth 从 src/utils/date.ts
 
 // Canvas / uCharts 绘图 - 修复版本
 const chartInstance = ref<any>(null)

+ 3 - 41
src/pages/health/details/blood-pressure.vue

@@ -95,6 +95,7 @@ import uCharts from '@qiun/ucharts'
 import CustomNav from '@/components/custom-nav.vue'
 import TabBar from '@/components/tab-bar.vue'
 import ScaleRuler from '@/components/scale-ruler.vue'
+import { getWeekStart, getWeekEnd, getWeekNumber, formatDisplayDate, formatPickerDate, daysInMonth, weekDayIndex } from '@/utils/date'
 
 type RecordItem = { id: string; date: string; s: number; d: number }
 
@@ -127,12 +128,7 @@ function getCanvasSize(): Promise<{ width: number; height: number }> {
   });
 }
 
-function formatPickerDate(d: Date) {
-  const y = d.getFullYear()
-  const m = String(d.getMonth() + 1).padStart(2, '0')
-  const day = String(d.getDate()).padStart(2, '0')
-  return `${y}-${m}-${day}`
-}
+// 使用 formatPickerDate 从 src/utils/date.ts
 
 const displayYear = computed(() => current.value.getFullYear())
 const displayMonth = computed(() => current.value.getMonth() + 1)
@@ -197,10 +193,6 @@ function aggregateDaily(recordsArr: RecordItem[], year: number, month: number) {
   return map
 }
 
-function formatDisplayDate(d: Date) {
-  return `${d.getFullYear()}-${String(d.getMonth() + 1).padStart(2, '0')}-${String(d.getDate()).padStart(2, '0')}`
-}
-
 const averageSystolic = computed(() => {
   if (records.value.length === 0) return '--'
   const sum = records.value.reduce((s, r) => s + r.s, 0)
@@ -212,37 +204,7 @@ const averageDiastolic = computed(() => {
   return Math.round(sum / records.value.length)
 })
 
-function daysInMonth(year: number, month: number) {
-  return new Date(year, month + 1, 0).getDate()
-}
-
-// 获取指定日期所在周的开始日期(星期一)
-function getWeekStart(date: Date): Date {
-  const d = new Date(date)
-  d.setHours(0, 0, 0, 0)
-  const day = d.getDay()
-  const diff = day === 0 ? -6 : 1 - day
-  d.setDate(d.getDate() + diff)
-  d.setHours(0, 0, 0, 0)
-  return d
-}
-
-// 获取指定日期所在周的结束日期(星期日)
-function getWeekEnd(date: Date): Date {
-  const d = getWeekStart(date)
-  d.setDate(d.getDate() + 6)
-  d.setHours(0, 0, 0, 0)
-  return d
-}
-
-// 获取指定日期所在周的周数(一年中的第几周)
-function getWeekNumber(date: Date): number {
-  const d = new Date(date)
-  d.setHours(0, 0, 0, 0)
-  d.setDate(d.getDate() + 4 - (d.getDay() || 7))
-  const yearStart = new Date(d.getFullYear(), 0, 1)
-  return Math.ceil(((d.getTime() - yearStart.getTime()) / 86400000 + 1) / 7)
-}
+// 使用共享日期工具 (src/utils/date.ts)
 
 // Canvas / uCharts 绘图 - 修复版本
 const chartInstance = ref<any>(null)

+ 5 - 36
src/pages/health/details/heart-rate.vue

@@ -86,6 +86,7 @@ import uCharts from '@qiun/ucharts'
 import CustomNav from '@/components/custom-nav.vue'
 import TabBar from '@/components/tab-bar.vue'
 import ScaleRuler from '@/components/scale-ruler.vue'
+import { getWeekStart, getWeekEnd, getWeekNumber, formatDisplayDate, formatPickerDate, daysInMonth, weekDayIndex } from '@/utils/date'
 
 type RecordItem = { id: string; date: string; hr: number }
 
@@ -118,12 +119,7 @@ function getCanvasSize(): Promise<{ width: number; height: number }> {
   });
 }
 
-function formatPickerDate(d: Date) {
-  const y = d.getFullYear()
-  const m = String(d.getMonth() + 1).padStart(2, '0')
-  const day = String(d.getDate()).padStart(2, '0')
-  return `${y}-${m}-${day}`
-}
+// 使用共享日期工具 (src/utils/date.ts)
 
 const displayYear = computed(() => current.value.getFullYear())
 const displayMonth = computed(() => current.value.getMonth() + 1)
@@ -166,30 +162,7 @@ function generateMockRecords(d: Date): RecordItem[] {
 }
 
 // 获取指定日期所在周的开始日期(星期一),并规范化到本地午夜
-function getWeekStart(date: Date): Date {
-  const d = new Date(date)
-  d.setHours(0, 0, 0, 0)
-  const day = d.getDay()
-  const diff = day === 0 ? -6 : 1 - day
-  d.setDate(d.getDate() + diff)
-  d.setHours(0, 0, 0, 0)
-  return d
-}
-
-function getWeekEnd(date: Date): Date {
-  const d = getWeekStart(date)
-  d.setDate(d.getDate() + 6)
-  d.setHours(0, 0, 0, 0)
-  return d
-}
-
-function getWeekNumber(date: Date): number {
-  const d = new Date(date)
-  d.setHours(0, 0, 0, 0)
-  d.setDate(d.getDate() + 4 - (d.getDay() || 7))
-  const yearStart = new Date(d.getFullYear(), 0, 1)
-  return Math.ceil(((d.getTime() - yearStart.getTime()) / 86400000 + 1) / 7)
-}
+// 使用共享日期工具 (src/utils/date.ts)
 
 // 将 records 聚合为每天一个点(取最新记录)
 function aggregateDaily(recordsArr: RecordItem[], year: number, month: number) {
@@ -210,9 +183,7 @@ function aggregateDaily(recordsArr: RecordItem[], year: number, month: number) {
   return map
 }
 
-function formatDisplayDate(d: Date) {
-  return `${d.getFullYear()}-${String(d.getMonth() + 1).padStart(2, '0')}-${String(d.getDate()).padStart(2, '0')}`
-}
+// 使用 formatDisplayDate 从 src/utils/date.ts
 
 const averageHR = computed(() => {
   if (records.value.length === 0) return '--'
@@ -220,9 +191,7 @@ const averageHR = computed(() => {
   return (sum / records.value.length).toFixed(0)
 })
 
-function daysInMonth(year: number, month: number) {
-  return new Date(year, month + 1, 0).getDate()
-}
+// 使用 daysInMonth 从 src/utils/date.ts
 
 // Canvas / uCharts 绘图 - 修复版本
 const chartInstance = ref<any>(null)

+ 3 - 42
src/pages/health/details/height.vue

@@ -87,6 +87,7 @@ import uCharts from '@qiun/ucharts'
 import CustomNav from '@/components/custom-nav.vue'
 import TabBar from '@/components/tab-bar.vue'
 import ScaleRuler from '@/components/scale-ruler.vue'
+import { getWeekStart, getWeekEnd, getWeekNumber, formatDisplayDate, formatPickerDate, daysInMonth, weekDayIndex } from '@/utils/date'
 
 type RecordItem = { id: string; date: string; height: number }
 
@@ -118,12 +119,7 @@ function getCanvasSize(): Promise<{ width: number; height: number }> {
   });
 }
 
-function formatPickerDate(d: Date) {
-  const y = d.getFullYear()
-  const m = String(d.getMonth() + 1).padStart(2, '0')
-  const day = String(d.getDate()).padStart(2, '0')
-  return `${y}-${m}-${day}`
-}
+// 使用 formatPickerDate 从 src/utils/date.ts
 
 const displayYear = computed(() => current.value.getFullYear())
 const displayMonth = computed(() => current.value.getMonth() + 1)
@@ -201,48 +197,13 @@ function aggregateDaily(recordsArr: RecordItem[], year: number, month: number) {
   return map
 }
 
-function formatDisplayDate(d: Date) {
-  return `${d.getFullYear()}-${String(d.getMonth() + 1).padStart(2, '0')}-${String(d.getDate()).padStart(2, '0')}`
-}
-
 const averageHeight = computed(() => {
   if (records.value.length === 0) return '--'
   const sum = records.value.reduce((s, r) => s + r.height, 0)
   return (sum / records.value.length).toFixed(1)
 })
 
-function daysInMonth(year: number, month: number) {
-  return new Date(year, month + 1, 0).getDate()
-}
-
-// 获取指定日期所在周的开始日期(星期一)
-function getWeekStart(date: Date): Date {
-  // 规范化到本地日期的00:00:00,避免时区/小时差异导致的比较不等问题
-  const d = new Date(date)
-  d.setHours(0, 0, 0, 0)
-  const day = d.getDay() // 0=周日, 1=周一, ..., 6=周六
-  const diff = day === 0 ? -6 : 1 - day // 调整为周一为开始
-  d.setDate(d.getDate() + diff)
-  d.setHours(0, 0, 0, 0)
-  return d
-}
-
-// 获取指定日期所在周的结束日期(星期日)
-function getWeekEnd(date: Date): Date {
-  const d = getWeekStart(date)
-  d.setDate(d.getDate() + 6)
-  d.setHours(0, 0, 0, 0)
-  return d
-}
-
-// 获取指定日期所在周的周数(一年中的第几周)
-function getWeekNumber(date: Date): number {
-  const d = new Date(date)
-  d.setHours(0, 0, 0, 0)
-  d.setDate(d.getDate() + 4 - (d.getDay() || 7)) // 调整到周四
-  const yearStart = new Date(d.getFullYear(), 0, 1)
-  return Math.ceil(((d.getTime() - yearStart.getTime()) / 86400000 + 1) / 7)
-}
+// 使用共享日期工具函数 (src/utils/date.ts)
 
 // Canvas / uCharts 绘图 - 修复版本
 const chartInstance = ref<any>(null)

+ 3 - 42
src/pages/health/details/weight.vue

@@ -85,6 +85,7 @@ import uCharts from '@qiun/ucharts'
 import CustomNav from '@/components/custom-nav.vue'
 import TabBar from '@/components/tab-bar.vue'
 import ScaleRuler from '@/components/scale-ruler.vue'
+import { getWeekStart, getWeekEnd, getWeekNumber, formatDisplayDate, formatPickerDate, daysInMonth, weekDayIndex } from '@/utils/date'
 
 type RecordItem = { id: string; date: string; weight: number }
 
@@ -116,12 +117,7 @@ function getCanvasSize(): Promise<{ width: number; height: number }> {
   });
 }
 
-function formatPickerDate(d: Date) {
-  const y = d.getFullYear()
-  const m = String(d.getMonth() + 1).padStart(2, '0')
-  const day = String(d.getDate()).padStart(2, '0')
-  return `${y}-${m}-${day}`
-}
+// 使用 formatPickerDate 从 src/utils/date.ts
 
 const displayYear = computed(() => current.value.getFullYear())
 const displayMonth = computed(() => current.value.getMonth() + 1)
@@ -193,47 +189,12 @@ function aggregateDaily(recordsArr: RecordItem[], year: number, month: number) {
   return map
 }
 
-function formatDisplayDate(d: Date) {
-  return `${d.getFullYear()}-${String(d.getMonth() + 1).padStart(2, '0')}-${String(d.getDate()).padStart(2, '0')}`
-}
-
 const averageWeight = computed(() => {
   if (records.value.length === 0) return '--'
   const sum = records.value.reduce((s, r) => s + r.weight, 0)
   return (sum / records.value.length).toFixed(1)
 })
-
-function daysInMonth(year: number, month: number) {
-  return new Date(year, month + 1, 0).getDate()
-}
-
-// 获取指定日期所在周的开始日期(星期一)
-function getWeekStart(date: Date): Date {
-  const d = new Date(date)
-  d.setHours(0, 0, 0, 0)
-  const day = d.getDay()
-  const diff = day === 0 ? -6 : 1 - day
-  d.setDate(d.getDate() + diff)
-  d.setHours(0, 0, 0, 0)
-  return d
-}
-
-// 获取指定日期所在周的结束日期(星期日)
-function getWeekEnd(date: Date): Date {
-  const d = getWeekStart(date)
-  d.setDate(d.getDate() + 6)
-  d.setHours(0, 0, 0, 0)
-  return d
-}
-
-// 获取指定日期所在周的周数(一年中的第几周)
-function getWeekNumber(date: Date): number {
-  const d = new Date(date)
-  d.setHours(0, 0, 0, 0)
-  d.setDate(d.getDate() + 4 - (d.getDay() || 7))
-  const yearStart = new Date(d.getFullYear(), 0, 1)
-  return Math.ceil(((d.getTime() - yearStart.getTime()) / 86400000 + 1) / 7)
-}
+// 使用共享日期工具 (src/utils/date.ts)
 
 // Canvas / uCharts 绘图 - 修复版本
 const chartInstance = ref<any>(null)

+ 53 - 0
src/utils/date.ts

@@ -0,0 +1,53 @@
+// 日期工具集:统一周/月计算与格式化,所有页面共享
+export function setToLocalMidnight(d: Date) {
+  const x = new Date(d)
+  x.setHours(0, 0, 0, 0)
+  return x
+}
+
+export function daysInMonth(year: number, month: number) {
+  return new Date(year, month + 1, 0).getDate()
+}
+
+export function formatDisplayDate(d: Date) {
+  const x = new Date(d)
+  const y = x.getFullYear()
+  const m = String(x.getMonth() + 1).padStart(2, '0')
+  const day = String(x.getDate()).padStart(2, '0')
+  return `${y}-${m}-${day}`
+}
+
+export function formatPickerDate(d: Date) {
+  return formatDisplayDate(d)
+}
+
+// 返回给定日期对应的周一(本地午夜)
+export function getWeekStart(date: Date): Date {
+  const d = setToLocalMidnight(date)
+  const day = d.getDay() // 0=Sun
+  const diff = day === 0 ? -6 : 1 - day
+  d.setDate(d.getDate() + diff)
+  return setToLocalMidnight(d)
+}
+
+// 返回该周的周日(本地午夜)
+export function getWeekEnd(date: Date): Date {
+  const d = getWeekStart(date)
+  d.setDate(d.getDate() + 6)
+  return setToLocalMidnight(d)
+}
+
+// ISO 风格的周数计算(一年中的第几周),与原实现保持一致
+export function getWeekNumber(date: Date): number {
+  const d = setToLocalMidnight(date)
+  d.setDate(d.getDate() + 4 - (d.getDay() || 7))
+  const yearStart = new Date(d.getFullYear(), 0, 1)
+  return Math.ceil(((d.getTime() - yearStart.getTime()) / 86400000 + 1) / 7)
+}
+
+// 计算 recordDate 在 weekStart 对应周内的索引 1..7,基于时间差,支持跨月
+export function weekDayIndex(recordDate: Date, weekStart: Date): number {
+  const r = setToLocalMidnight(recordDate).getTime()
+  const w = setToLocalMidnight(weekStart).getTime()
+  return Math.round((r - w) / 86400000) + 1
+}