|
|
@@ -83,7 +83,7 @@
|
|
|
|
|
|
<script setup lang="ts">
|
|
|
import { ref, computed, onMounted, watch, nextTick, onBeforeUnmount, getCurrentInstance } from 'vue'
|
|
|
-import uCharts from '@qiun/ucharts'
|
|
|
+import { createUChart } from '@/composables/useUChart'
|
|
|
import CustomNav from '@/components/custom-nav.vue'
|
|
|
import TabBar from '@/components/tab-bar.vue'
|
|
|
import ScaleRuler from '@/components/scale-ruler.vue'
|
|
|
@@ -205,448 +205,20 @@ const averageHeight = computed(() => {
|
|
|
|
|
|
// 使用共享日期工具函数 (src/utils/date.ts)
|
|
|
|
|
|
-// Canvas / uCharts 绘图 - 修复版本
|
|
|
-const chartInstance = ref<any>(null)
|
|
|
+// 使用 createUChart composable
|
|
|
const vm = getCurrentInstance()
|
|
|
-let chartInitialized = false
|
|
|
-let chartBusy = false // 绘图锁,防止并发初始化/更新
|
|
|
-
|
|
|
-// 简化的图表绘制函数
|
|
|
-async function drawChart() {
|
|
|
- // 防止并发调用
|
|
|
- if (chartBusy) return
|
|
|
- chartBusy = true
|
|
|
-
|
|
|
- // 防止重复初始化(已初始化则更新数据)
|
|
|
- if (chartInitialized && chartInstance.value) {
|
|
|
- try {
|
|
|
- await updateChartData()
|
|
|
- } finally {
|
|
|
- chartBusy = false
|
|
|
- }
|
|
|
- return
|
|
|
- }
|
|
|
-
|
|
|
- // 清理旧实例
|
|
|
- if (chartInstance.value) {
|
|
|
- try {
|
|
|
- if (chartInstance.value.destroy) {
|
|
|
- chartInstance.value.destroy()
|
|
|
- }
|
|
|
- } catch (e) {
|
|
|
- console.warn('Destroy chart error:', e)
|
|
|
- }
|
|
|
- chartInstance.value = null
|
|
|
- }
|
|
|
-
|
|
|
- if (typeof uCharts === 'undefined') {
|
|
|
- console.warn('uCharts not available')
|
|
|
- return
|
|
|
- }
|
|
|
-
|
|
|
- // 动态获取 Canvas 容器的宽高 (单位: px)
|
|
|
- const size = await getCanvasSize();
|
|
|
- const cssWidth = size.width;
|
|
|
- const cssHeight = size.height;
|
|
|
-
|
|
|
- // 获取可靠的设备像素比 - 固定为1避免高分辨率设备上元素过大
|
|
|
- const pixelRatio = 1; // 关键修复:固定pixelRatio为1
|
|
|
-
|
|
|
- // 为避免 X 轴标签或绘图区域右侧溢出,保留右侧间距,让绘图区域略窄于 canvas
|
|
|
- const rightGap = Math.max(24, Math.round(cssWidth * 0.04)) // 最小 24px 或 4% 屏宽
|
|
|
- const chartWidth = Math.max(cssWidth - rightGap, Math.round(cssWidth * 0.85))
|
|
|
-
|
|
|
- console.log('Canvas 尺寸与像素比:', { cssWidth, cssHeight, pixelRatio });
|
|
|
-
|
|
|
- const year = current.value.getFullYear()
|
|
|
- const month = current.value.getMonth()
|
|
|
- let categories: string[] = []
|
|
|
- let showLabelDays: number[] = []
|
|
|
-
|
|
|
- if (viewMode.value === 'month') {
|
|
|
- // 月视图
|
|
|
- const days = daysInMonth(year, month)
|
|
|
- // 选择要显示的标签:1号、中间几天、最后一天
|
|
|
- if (days > 0) {
|
|
|
- showLabelDays.push(1) // 第1天
|
|
|
- if (days > 1) showLabelDays.push(days) // 最后一天
|
|
|
- // 中间添加2-3个关键点
|
|
|
- if (days > 7) showLabelDays.push(Math.ceil(days / 3))
|
|
|
- if (days > 14) showLabelDays.push(Math.ceil(days * 2 / 3))
|
|
|
- }
|
|
|
-
|
|
|
- for (let d = 1; d <= days; d++) {
|
|
|
- if (showLabelDays.includes(d)) {
|
|
|
- categories.push(`${d}日`)
|
|
|
- } else {
|
|
|
- categories.push('')
|
|
|
- }
|
|
|
- }
|
|
|
- } else {
|
|
|
- // 周视图:显示星期一到星期日
|
|
|
- const weekStart = getWeekStart(current.value)
|
|
|
- const weekDays = ['一', '二', '三', '四', '五', '六', '日']
|
|
|
- for (let i = 0; i < 7; i++) {
|
|
|
- const date = new Date(weekStart)
|
|
|
- date.setDate(weekStart.getDate() + i)
|
|
|
- categories.push(`${date.getDate()}日(${weekDays[i]})`)
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- // 只为有记录的天生成categories和data,避免将无数据天设为0
|
|
|
- const data: number[] = []
|
|
|
- const filteredCategories: string[] = []
|
|
|
- // 使用Map按日聚合,保留最新记录(records 数组头部为最新)
|
|
|
- const dayMap = new Map<number, RecordItem>()
|
|
|
-
|
|
|
- if (viewMode.value === 'month') {
|
|
|
- // 月视图:按日期聚合
|
|
|
- for (const r of records.value) {
|
|
|
- const parts = r.date.split('-')
|
|
|
- if (parts.length >= 3) {
|
|
|
- const y = parseInt(parts[0], 10)
|
|
|
- const m = parseInt(parts[1], 10) - 1
|
|
|
- const d = parseInt(parts[2], 10)
|
|
|
- if (y === year && m === month) {
|
|
|
- // 以最后遍历到的(数组顺序保证头部为最新)作为最终值
|
|
|
- dayMap.set(d, r)
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- // 将有数据的日期按日顺序输出
|
|
|
- const sortedDays = Array.from(dayMap.keys()).sort((a, b) => a - b)
|
|
|
- for (const d of sortedDays) {
|
|
|
- const rec = dayMap.get(d)!
|
|
|
- filteredCategories.push(`${d}日`)
|
|
|
- data.push(rec.height)
|
|
|
- }
|
|
|
- } else {
|
|
|
- // 周视图:按星期聚合
|
|
|
- const weekStart = getWeekStart(current.value)
|
|
|
- for (const r of records.value) {
|
|
|
- const parts = r.date.split('-')
|
|
|
- if (parts.length >= 3) {
|
|
|
- const recordDate = new Date(parseInt(parts[0], 10), parseInt(parts[1], 10) - 1, parseInt(parts[2], 10))
|
|
|
- const weekStartDate = getWeekStart(recordDate)
|
|
|
- // 检查记录是否在本周内
|
|
|
- if (weekStartDate.getTime() === weekStart.getTime()) {
|
|
|
- const dayOfWeek = recordDate.getDay() || 7 // 0=周日,转换为7
|
|
|
- dayMap.set(dayOfWeek, r)
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- // 按星期一到星期日顺序输出
|
|
|
- const weekDays = ['一', '二', '三', '四', '五', '六', '日']
|
|
|
- for (let i = 1; i <= 7; i++) {
|
|
|
- const rec = dayMap.get(i)
|
|
|
- if (rec) {
|
|
|
- const date = new Date(rec.date)
|
|
|
- filteredCategories.push(`${date.getDate()}日(${weekDays[i-1]})`)
|
|
|
- data.push(rec.height)
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- // 如果没有任何数据,则回退为整月/周空数据(避免 uCharts 抛错)
|
|
|
- const categoriesToUse = filteredCategories.length ? filteredCategories : categories
|
|
|
-
|
|
|
- // 计算合理的Y轴范围
|
|
|
- const validData = data.filter(v => v > 0)
|
|
|
- const minVal = validData.length ? Math.floor(Math.min(...validData)) - 2 : 140
|
|
|
- const maxVal = validData.length ? Math.ceil(Math.max(...validData)) + 2 : 200
|
|
|
-
|
|
|
- const series = [{
|
|
|
- name: '身高',
|
|
|
- data: data,
|
|
|
- color: '#ff6a00'
|
|
|
- }]
|
|
|
-
|
|
|
- // 获取canvas上下文
|
|
|
- let ctx: any = null
|
|
|
- try {
|
|
|
- if (typeof uni !== 'undefined' && typeof uni.createCanvasContext === 'function') {
|
|
|
- // 小程序环境:优先尝试传入组件实例
|
|
|
- try {
|
|
|
- ctx = vm?.proxy ? uni.createCanvasContext('heightChart', vm.proxy) : uni.createCanvasContext('heightChart')
|
|
|
- } catch (e) {
|
|
|
- // 再尝试不传vm
|
|
|
- try { ctx = uni.createCanvasContext('heightChart') } catch (err) { ctx = null }
|
|
|
- }
|
|
|
- }
|
|
|
- } catch (e) {
|
|
|
- ctx = null
|
|
|
- }
|
|
|
-
|
|
|
- // H5环境尝试使用DOM获取2D上下文
|
|
|
- if (!ctx && typeof document !== 'undefined') {
|
|
|
- try {
|
|
|
- // 重试逻辑:初次可能未渲染到 DOM
|
|
|
- let el: HTMLCanvasElement | null = null
|
|
|
- for (let attempt = 0; attempt < 3; attempt++) {
|
|
|
- el = document.getElementById('heightChart') as HTMLCanvasElement | null
|
|
|
- if (el) break
|
|
|
- // 短延迟后重试(非阻塞)
|
|
|
- await new Promise(r => setTimeout(r, 50))
|
|
|
- }
|
|
|
-
|
|
|
- if (el && el.getContext) {
|
|
|
- // Ensure canvas actual pixel size matches cssWidth * pixelRatio
|
|
|
- try {
|
|
|
- const physicalW = Math.floor(cssWidth * pixelRatio)
|
|
|
- const physicalH = Math.floor(cssHeight * pixelRatio)
|
|
|
- if (el.width !== physicalW || el.height !== physicalH) {
|
|
|
- el.width = physicalW
|
|
|
- el.height = physicalH
|
|
|
- // also adjust style to keep layout consistent
|
|
|
- el.style.width = cssWidth + 'px'
|
|
|
- el.style.height = cssHeight + 'px'
|
|
|
- }
|
|
|
- } catch (e) {
|
|
|
- console.warn('Set canvas physical size failed', e)
|
|
|
- }
|
|
|
- ctx = el.getContext('2d')
|
|
|
- }
|
|
|
- } catch (e) {
|
|
|
- ctx = null
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- if (!ctx) {
|
|
|
- console.warn('Unable to obtain canvas context for uCharts. Ensure canvas-id matches and vm proxy is available on mini-program.')
|
|
|
- return
|
|
|
- }
|
|
|
-
|
|
|
- console.log('Canvas config:', {
|
|
|
- width: cssWidth,
|
|
|
- height: cssHeight,
|
|
|
- pixelRatio,
|
|
|
- categoriesLength: categories.length,
|
|
|
- dataPoints: data.length
|
|
|
- })
|
|
|
-
|
|
|
- // 简化的uCharts配置 - 关闭所有可能产生重叠的选项
|
|
|
- const config = {
|
|
|
- $this: vm?.proxy,
|
|
|
- canvasId: 'heightChart',
|
|
|
- context: ctx,
|
|
|
- type: 'line',
|
|
|
- fontSize: 10, // 全局字体大小,参考微信小程序示例
|
|
|
- categories: categoriesToUse,
|
|
|
- series: series,
|
|
|
- // 使用比 canvas 略窄的绘图宽度并设置 padding 来避免右边溢出
|
|
|
- width: chartWidth,
|
|
|
- padding: [10, rightGap + 8, 18, 10],
|
|
|
- height: cssHeight,
|
|
|
- pixelRatio: pixelRatio,
|
|
|
- background: 'transparent',
|
|
|
- animation: false, // 关闭动画避免干扰
|
|
|
- enableScroll: false,
|
|
|
- dataLabel: false, // 关键:关闭数据点标签
|
|
|
- legend: {
|
|
|
- show: false
|
|
|
- },
|
|
|
- xAxis: {
|
|
|
- disableGrid: true, // 简化网格
|
|
|
- axisLine: true,
|
|
|
- axisLineColor: '#e0e0e0',
|
|
|
- fontColor: '#666666',
|
|
|
- fontSize: 10, // 进一步调小X轴字体
|
|
|
- boundaryGap: 'justify'
|
|
|
- },
|
|
|
- yAxis: {
|
|
|
- disableGrid: false,
|
|
|
- gridColor: '#f5f5f5',
|
|
|
- splitNumber: 4, // 减少分割数
|
|
|
- min: minVal,
|
|
|
- max: maxVal,
|
|
|
- axisLine: true,
|
|
|
- axisLineColor: '#e0e0e0',
|
|
|
- fontColor: '#666666',
|
|
|
- fontSize: 10, // 进一步调小Y轴字体
|
|
|
- format: (val: number) => val % 1 === 0 ? `${val}cm` : '' // 只显示整数值
|
|
|
- },
|
|
|
- extra: {
|
|
|
- line: {
|
|
|
- type: 'curve',
|
|
|
- width: 1, // 进一步调细线宽
|
|
|
- activeType: 'point', // 简化点样式
|
|
|
- point: {
|
|
|
- radius: 0.5, // 进一步调小数据点半径
|
|
|
- strokeWidth: 0.5 // 调小边框宽度
|
|
|
- }
|
|
|
- },
|
|
|
- tooltip: {
|
|
|
- showBox: false, // 关闭提示框避免重叠
|
|
|
- showCategory: false
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- try {
|
|
|
- // 在创建新实例前确保销毁旧实例
|
|
|
- if (chartInstance.value && chartInstance.value.destroy) {
|
|
|
- try { chartInstance.value.destroy() } catch (e) { console.warn('destroy before init failed', e) }
|
|
|
- chartInstance.value = null
|
|
|
- chartInitialized = false
|
|
|
- }
|
|
|
-
|
|
|
- chartInstance.value = new uCharts(config)
|
|
|
- chartInitialized = true
|
|
|
- console.log('uCharts initialized successfully')
|
|
|
- } catch (error) {
|
|
|
- console.error('uCharts init error:', error)
|
|
|
- chartInitialized = false
|
|
|
- }
|
|
|
- chartBusy = false
|
|
|
-}
|
|
|
-
|
|
|
-// 更新数据而不重新初始化
|
|
|
-async function updateChartData() {
|
|
|
- if (chartBusy) return
|
|
|
- chartBusy = true
|
|
|
-
|
|
|
- if (!chartInstance.value || !chartInitialized) {
|
|
|
- try {
|
|
|
- await drawChart()
|
|
|
- } finally {
|
|
|
- chartBusy = false
|
|
|
- }
|
|
|
- return
|
|
|
- }
|
|
|
-
|
|
|
- const year = current.value.getFullYear()
|
|
|
- const month = current.value.getMonth()
|
|
|
-
|
|
|
- let categories: string[] = []
|
|
|
- let showLabelDays: number[] = []
|
|
|
-
|
|
|
- if (viewMode.value === 'month') {
|
|
|
- // 月视图
|
|
|
- const days = daysInMonth(year, month)
|
|
|
- if (days > 0) {
|
|
|
- showLabelDays.push(1)
|
|
|
- if (days > 1) showLabelDays.push(days)
|
|
|
- if (days > 7) showLabelDays.push(Math.ceil(days / 3))
|
|
|
- if (days > 14) showLabelDays.push(Math.ceil(days * 2 / 3))
|
|
|
- }
|
|
|
-
|
|
|
- for (let d = 1; d <= days; d++) {
|
|
|
- if (showLabelDays.includes(d)) {
|
|
|
- categories.push(`${d}日`)
|
|
|
- } else {
|
|
|
- categories.push('')
|
|
|
- }
|
|
|
- }
|
|
|
- } else {
|
|
|
- // 周视图
|
|
|
- const weekStart = getWeekStart(current.value)
|
|
|
- const weekDays = ['一', '二', '三', '四', '五', '六', '日']
|
|
|
- for (let i = 0; i < 7; i++) {
|
|
|
- const date = new Date(weekStart)
|
|
|
- date.setDate(weekStart.getDate() + i)
|
|
|
- categories.push(`${date.getDate()}日(${weekDays[i]})`)
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- // 只为有记录的天生成categories和data
|
|
|
- const data: number[] = []
|
|
|
- const filteredCategories: string[] = []
|
|
|
- const dayMap = new Map<number, RecordItem>()
|
|
|
-
|
|
|
- if (viewMode.value === 'month') {
|
|
|
- for (const r of records.value) {
|
|
|
- const parts = r.date.split('-')
|
|
|
- if (parts.length >= 3) {
|
|
|
- const y = parseInt(parts[0], 10)
|
|
|
- const m = parseInt(parts[1], 10) - 1
|
|
|
- const d = parseInt(parts[2], 10)
|
|
|
- if (y === year && m === month) {
|
|
|
- dayMap.set(d, r)
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
- const sortedDays = Array.from(dayMap.keys()).sort((a, b) => a - b)
|
|
|
- for (const d of sortedDays) {
|
|
|
- const rec = dayMap.get(d)!
|
|
|
- filteredCategories.push(`${d}日`)
|
|
|
- data.push(rec.height)
|
|
|
- }
|
|
|
- } else {
|
|
|
- const weekStart = getWeekStart(current.value)
|
|
|
- for (const r of records.value) {
|
|
|
- const parts = r.date.split('-')
|
|
|
- if (parts.length >= 3) {
|
|
|
- const recordDate = new Date(parseInt(parts[0], 10), parseInt(parts[1], 10) - 1, parseInt(parts[2], 10))
|
|
|
- const weekStartDate = getWeekStart(recordDate)
|
|
|
- if (weekStartDate.getTime() === weekStart.getTime()) {
|
|
|
- const dayOfWeek = recordDate.getDay() || 7
|
|
|
- dayMap.set(dayOfWeek, r)
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
- const weekDays = ['一', '二', '三', '四', '五', '六', '日']
|
|
|
- for (let i = 1; i <= 7; i++) {
|
|
|
- const rec = dayMap.get(i)
|
|
|
- if (rec) {
|
|
|
- const date = new Date(rec.date)
|
|
|
- filteredCategories.push(`${date.getDate()}日(${weekDays[i-1]})`)
|
|
|
- data.push(rec.height)
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- const categoriesToUse = filteredCategories.length ? filteredCategories : categories
|
|
|
-
|
|
|
- const validData = data.filter(v => v > 0)
|
|
|
- const minVal = validData.length ? Math.floor(Math.min(...validData)) - 2 : 140
|
|
|
- const maxVal = validData.length ? Math.ceil(Math.max(...validData)) + 2 : 200
|
|
|
-
|
|
|
- try {
|
|
|
- // 使用uCharts的更新方法,仅更新有数据的分类和序列
|
|
|
- // 若实例存在,先更新宽度/padding(如果有配置)以避免右侧溢出
|
|
|
- try {
|
|
|
- const size = await getCanvasSize()
|
|
|
- const cssWidth = size.width
|
|
|
- const rightGap = Math.max(24, Math.round(cssWidth * 0.04))
|
|
|
- const chartWidth = Math.max(cssWidth - rightGap, Math.round(cssWidth * 0.85))
|
|
|
- if (chartInstance.value.opts) {
|
|
|
- chartInstance.value.opts.width = chartWidth
|
|
|
- chartInstance.value.opts.padding = [10, rightGap + 8, 18, 10]
|
|
|
- }
|
|
|
- } catch (e) {
|
|
|
- // 忽略尺寸更新错误
|
|
|
- }
|
|
|
+const heightChart = createUChart({
|
|
|
+ canvasId: 'heightChart',
|
|
|
+ vm,
|
|
|
+ getCanvasSize,
|
|
|
+ seriesNames: '身高',
|
|
|
+ valueAccessors: r => r.height,
|
|
|
+ colors: '#ff6a00'
|
|
|
+})
|
|
|
|
|
|
- chartInstance.value.updateData({
|
|
|
- categories: categoriesToUse,
|
|
|
- series: [{
|
|
|
- name: '身高',
|
|
|
- data: data,
|
|
|
- color: '#ff6a00'
|
|
|
- }]
|
|
|
- })
|
|
|
|
|
|
- // 更新Y轴范围
|
|
|
- chartInstance.value.opts.yAxis.min = minVal
|
|
|
- chartInstance.value.opts.yAxis.max = maxVal
|
|
|
-
|
|
|
- } catch (error) {
|
|
|
- console.error('Update chart error:', error)
|
|
|
- // 如果更新失败,重新销毁并重建实例
|
|
|
- try {
|
|
|
- if (chartInstance.value && chartInstance.value.destroy) chartInstance.value.destroy()
|
|
|
- } catch (e) { console.warn('destroy on update failure failed', e) }
|
|
|
- chartInstance.value = null
|
|
|
- chartInitialized = false
|
|
|
- try {
|
|
|
- await drawChart()
|
|
|
- } catch (e) { console.error('re-init after update failure also failed', e) }
|
|
|
- }
|
|
|
- chartBusy = false
|
|
|
-}
|
|
|
|
|
|
+// 生命周期钩子
|
|
|
onMounted(() => {
|
|
|
// 延迟确保DOM渲染完成
|
|
|
setTimeout(async () => {
|
|
|
@@ -659,61 +231,27 @@ onMounted(() => {
|
|
|
} catch (e) {
|
|
|
console.warn('getCanvasSize failed on mounted', e)
|
|
|
}
|
|
|
- await drawChart()
|
|
|
+ await heightChart.draw(records, current, viewMode)
|
|
|
}, 500)
|
|
|
})
|
|
|
|
|
|
// 简化监听,避免频繁重绘
|
|
|
watch([() => current.value], async () => {
|
|
|
setTimeout(async () => {
|
|
|
- await updateChartData()
|
|
|
+ await heightChart.update(records, current, viewMode)
|
|
|
}, 100)
|
|
|
})
|
|
|
|
|
|
watch([() => records.value], async () => {
|
|
|
setTimeout(async () => {
|
|
|
- await updateChartData()
|
|
|
+ await heightChart.update(records, current, viewMode)
|
|
|
}, 100)
|
|
|
}, { deep: true })
|
|
|
|
|
|
onBeforeUnmount(() => {
|
|
|
- if (chartInstance.value && chartInstance.value.destroy) {
|
|
|
- try {
|
|
|
- chartInstance.value.destroy()
|
|
|
- } catch (e) {
|
|
|
- console.warn('uCharts destroy error:', e)
|
|
|
- }
|
|
|
- }
|
|
|
- chartInstance.value = null
|
|
|
- chartInitialized = false
|
|
|
+ heightChart.destroy()
|
|
|
})
|
|
|
|
|
|
-// 强制重建图表(用于切换月份时彻底刷新,如同退出页面再进入)
|
|
|
-async function rebuildChart() {
|
|
|
- // 如果正在绘制,等一小会儿再销毁
|
|
|
- if (chartBusy) {
|
|
|
- // 等待最大 300ms,避免长时间阻塞
|
|
|
- await new Promise(r => setTimeout(r, 50))
|
|
|
- }
|
|
|
- try {
|
|
|
- if (chartInstance.value && chartInstance.value.destroy) {
|
|
|
- try { chartInstance.value.destroy() } catch (e) { console.warn('destroy in rebuildChart failed', e) }
|
|
|
- }
|
|
|
- } catch (e) {
|
|
|
- console.warn('rebuildChart destroy error', e)
|
|
|
- }
|
|
|
- chartInstance.value = null
|
|
|
- chartInitialized = false
|
|
|
- // 等待 DOM/Tick 稳定
|
|
|
- await nextTick()
|
|
|
- // 重新初始化
|
|
|
- try {
|
|
|
- await drawChart()
|
|
|
- } catch (e) {
|
|
|
- console.error('rebuildChart drawChart failed', e)
|
|
|
- }
|
|
|
-}
|
|
|
-
|
|
|
// 其他函数保持不变
|
|
|
async function prevPeriod() {
|
|
|
const d = new Date(current.value)
|
|
|
@@ -725,7 +263,7 @@ async function prevPeriod() {
|
|
|
current.value = d
|
|
|
pickerValue.value = [d.getFullYear() - 2000, d.getMonth()]
|
|
|
records.value = generateMockRecords(d)
|
|
|
- await rebuildChart()
|
|
|
+ await heightChart.rebuild(records, current, viewMode)
|
|
|
}
|
|
|
|
|
|
async function nextPeriod() {
|
|
|
@@ -738,7 +276,7 @@ async function nextPeriod() {
|
|
|
current.value = d
|
|
|
pickerValue.value = [d.getFullYear() - 2000, d.getMonth()]
|
|
|
records.value = generateMockRecords(d)
|
|
|
- await rebuildChart()
|
|
|
+ await heightChart.rebuild(records, current, viewMode)
|
|
|
}
|
|
|
|
|
|
async function setViewMode(mode: 'month' | 'week') {
|
|
|
@@ -746,7 +284,7 @@ async function setViewMode(mode: 'month' | 'week') {
|
|
|
viewMode.value = mode
|
|
|
// 重新生成数据和图表
|
|
|
records.value = generateMockRecords(current.value)
|
|
|
- await rebuildChart()
|
|
|
+ await heightChart.rebuild(records, current, viewMode)
|
|
|
}
|
|
|
}
|
|
|
|
|
|
@@ -759,7 +297,7 @@ async function onPickerChange(e: any) {
|
|
|
current.value = d
|
|
|
pickerValue.value = [val[0], val[1]]
|
|
|
records.value = generateMockRecords(d)
|
|
|
- await rebuildChart()
|
|
|
+ await heightChart.rebuild(records, current, viewMode)
|
|
|
}
|
|
|
}
|
|
|
|
|
|
@@ -823,7 +361,7 @@ async function confirmAdd() {
|
|
|
closeAdd()
|
|
|
// 新增记录后彻底重建图表,确保像退出再进入一样刷新
|
|
|
try {
|
|
|
- await rebuildChart()
|
|
|
+ await heightChart.rebuild(records, current, viewMode)
|
|
|
} catch (e) {
|
|
|
console.warn('rebuildChart after add failed', e)
|
|
|
}
|
|
|
@@ -837,13 +375,13 @@ async function confirmDeleteRecord(id: string) {
|
|
|
success: async (res: any) => {
|
|
|
if (res.confirm) {
|
|
|
records.value = records.value.filter(r => r.id !== id)
|
|
|
- try { await rebuildChart() } catch (e) { console.warn('rebuildChart after delete failed', e) }
|
|
|
+ try { await heightChart.rebuild(records, current, viewMode) } catch (e) { console.warn('rebuildChart after delete failed', e) }
|
|
|
}
|
|
|
}
|
|
|
})
|
|
|
} else {
|
|
|
records.value = records.value.filter(r => r.id !== id)
|
|
|
- try { await rebuildChart() } catch (e) { console.warn('rebuildChart after delete failed', e) }
|
|
|
+ try { await heightChart.rebuild(records, current, viewMode) } catch (e) { console.warn('rebuildChart after delete failed', e) }
|
|
|
}
|
|
|
}
|
|
|
</script>
|