diff --git a/TUICallKit-Vue3/main.js b/TUICallKit-Vue3/main.js index 5fd1d831..f1d13fa0 100644 --- a/TUICallKit-Vue3/main.js +++ b/TUICallKit-Vue3/main.js @@ -1,5 +1,5 @@ import App from './App' -var baseUrl ='https://admin.zhenyangtang.com.cn/'; +var baseUrl ='https://css.zhenyangtang.com.cn/'; // #ifndef VUE3 import Vue from 'vue' import './uni.promisify.adaptor' diff --git a/TUICallKit-Vue3/tongji/pages/index.vue b/TUICallKit-Vue3/tongji/pages/index.vue index a1374ce0..0b254e0d 100644 --- a/TUICallKit-Vue3/tongji/pages/index.vue +++ b/TUICallKit-Vue3/tongji/pages/index.vue @@ -222,17 +222,24 @@ {{ todayChecked ? '今日血糖已记录' : '今日还没记血糖' }} - - - {{ card.patient_name || '就诊卡' }} + + + + {{ card.patient_name || '就诊卡' }} + - + @@ -246,45 +253,12 @@ @click="ttsSpeaking ? ttsStop() : speakLatestSummary()" > - {{ ttsSpeaking ? '停止朗读' : '朗读最新血糖' }} + {{ ttsSpeaking ? '停止朗读' : '朗读血糖' }} - - - 今日血糖 - - - {{ elderFasting.label }} - - {{ elderFasting.value }} - mmol/L - - 偏高,请遵医嘱 - - - {{ elderPostprandial.label }} - - {{ elderPostprandial.value }} - mmol/L - - 偏高,请遵医嘱 - - - - - - - - - {{ opt.label }} - - + + + @@ -292,11 +266,19 @@ {{ rangeText }} · mmol/L - + 空腹 - + 餐后 @@ -344,7 +326,41 @@ + + + {{ opt.label }} + + + + 今日血糖 + + + {{ elderFasting.label }} + + {{ elderFasting.value }} + mmol/L + + 偏高,请遵医嘱 + + + {{ elderPostprandial.label }} + + {{ elderPostprandial.value }} + mmol/L + + 偏高,请遵医嘱 + + + + + @@ -375,7 +391,7 @@ 加载今日数据中… - + 请如实填写,留空表示该项不上传。当天可多次修改。 @@ -565,6 +581,8 @@ const trackingNotes = ref([]) const hoverInfo = ref(null) let hoverTimer = null +const chartSeriesVisible = ref({ fasting: true, postprandial: true }) + // 画布上下文相关 let canvasNode = null let canvasCtx = null @@ -887,29 +905,13 @@ function elderMetricFromBlood(blood, field, label) { const todayBlood = computed(() => bloodByDate.value[todayStr.value] || null) -const elderFasting = computed(() => { - const today = todayBlood.value - if (today && toNumber(today.fasting_blood_sugar) !== null) { - return elderMetricFromBlood(today, 'fasting_blood_sugar', '空腹') - } - const latest = latestStat.value.fasting - if (latest.value !== '—') { - return { label: '空腹(最近)', value: latest.value, isHigh: latest.isHigh } - } - return { label: '空腹', value: '—', isHigh: false } -}) +const elderFasting = computed(() => + elderMetricFromBlood(todayBlood.value, 'fasting_blood_sugar', '空腹') +) -const elderPostprandial = computed(() => { - const today = todayBlood.value - if (today && toNumber(today.postprandial_blood_sugar) !== null) { - return elderMetricFromBlood(today, 'postprandial_blood_sugar', '餐后') - } - const latest = latestStat.value.postprandial - if (latest.value !== '—') { - return { label: '餐后(最近)', value: latest.value, isHigh: latest.isHigh } - } - return { label: '餐后', value: '—', isHigh: false } -}) +const elderPostprandial = computed(() => + elderMetricFromBlood(todayBlood.value, 'postprandial_blood_sugar', '餐后') +) // 给某天某字段计算 day-over-day 趋势(用于日常记录列表的指标小标签) function getDayTrend(date, field, precision = 1) { @@ -1800,8 +1802,8 @@ function buildSeries(field) { }) } -function computeYRange(series1, series2) { - const values = [...series1, ...series2].filter((v) => v !== null) +function computeYRange(...seriesList) { + const values = seriesList.flat().filter((v) => v !== null) if (!values.length) return { yMin: 4, yMax: 12 } let min = Math.min(...values) let max = Math.max(...values) @@ -1835,9 +1837,33 @@ function drawChart() { const fastingSeries = buildSeries('fasting_blood_sugar') const postSeries = buildSeries('postprandial_blood_sugar') - const { yMin, yMax } = computeYRange(fastingSeries, postSeries) const n = chartDates.value.length const threshold = getBloodSugarThresholds(age.value) + const seriesDefs = [ + { + key: 'fasting', + data: fastingSeries, + color: '#204E2B', + fillTop: 'rgba(32,78,43,0.18)', + fillBottom: 'rgba(32,78,43,0)', + label: '空腹', + highThreshold: threshold ? threshold.fasting : null + }, + { + key: 'postprandial', + data: postSeries, + color: '#D97706', + fillTop: 'rgba(217,119,6,0.18)', + fillBottom: 'rgba(217,119,6,0)', + label: '餐后', + highThreshold: threshold ? threshold.postprandial : null + } + ] + const visibleDefs = seriesDefs.filter((item) => chartSeriesVisible.value[item.key]) + const rangeSources = visibleDefs.length + ? visibleDefs.map((item) => item.data) + : [fastingSeries, postSeries] + const { yMin, yMax } = computeYRange(...rangeSources) const valueToY = (v) => padding.top + ch * (1 - (v - yMin) / (yMax - yMin)) // 1) 背景:纯净浅色 + 阈值以上一抹极淡红 @@ -1915,37 +1941,20 @@ function drawChart() { } // 5) 绘制曲线 - const seriesMeta = [ - { - data: fastingSeries, - color: '#204E2B', - fillTop: 'rgba(32,78,43,0.18)', - fillBottom: 'rgba(32,78,43,0)', - label: '空腹', - highThreshold: threshold ? threshold.fasting : null - }, - { - data: postSeries, - color: '#386641', - fillTop: 'rgba(56,102,65,0.14)', - fillBottom: 'rgba(56,102,65,0)', - label: '餐后', - highThreshold: threshold ? threshold.postprandial : null - } - ] - const xAt = (i) => (n === 1 ? padding.left + cw / 2 : padding.left + (cw * i) / (n - 1)) - const coordCache = [] + const coordByKey = { fasting: [], postprandial: [] } // 7 天内显示圆点,30 天以纯曲线为主 const showDots = n <= 10 - seriesMeta.forEach((meta) => { + seriesDefs.forEach((meta) => { const projected = meta.data.map((v, i) => ({ x: xAt(i), y: v === null ? null : valueToY(v), value: v })) - coordCache.push(projected) + coordByKey[meta.key] = projected + + if (!chartSeriesVisible.value[meta.key]) return const segments = [] let cur = [] @@ -2066,11 +2075,18 @@ function drawChart() { cw, ch, n, - fasting: coordCache[0] || [], - postprandial: coordCache[1] || [] + fasting: coordByKey.fasting, + postprandial: coordByKey.postprandial } } +function toggleChartSeries(key) { + if (key !== 'fasting' && key !== 'postprandial') return + chartSeriesVisible.value[key] = !chartSeriesVisible.value[key] + hoverInfo.value = null + scheduleChartRedraw() +} + function onChartTouch(e) { if (!chartCoords || !canvasWidth) return if (!chartDates.value.length) return @@ -2089,8 +2105,8 @@ function onChartTouch(e) { if (idx < 0) idx = 0 if (idx > n - 1) idx = n - 1 const date = chartDates.value[idx] - const fp = chartCoords.fasting[idx] - const pp = chartCoords.postprandial[idx] + const fp = chartSeriesVisible.value.fasting ? chartCoords.fasting[idx] : null + const pp = chartSeriesVisible.value.postprandial ? chartCoords.postprandial[idx] : null const anchorX = fp?.x ?? pp?.x ?? padding.left + cw * (idx / Math.max(1, n - 1)) const left = Math.max(8, Math.min(canvasWidth - 130, anchorX - 60)) @@ -2970,8 +2986,7 @@ async function onFamilyLike() { .card { background: #ffffff; border-radius: var(--radius-card); - margin: 28rpx 24rpx 0; - padding: 30rpx 28rpx; + padding: 30rpx 15rpx; box-shadow: var(--shadow-premium); animation: card-rise 0.45s ease-out both; } @@ -3039,8 +3054,22 @@ async function onFamilyLike() { display: flex; align-items: center; gap: 8rpx; + padding: 8rpx 12rpx; + margin: -8rpx -12rpx; font-size: 22rpx; color: var(--slate-600); + border-radius: 999rpx; + transition: opacity 0.2s ease; + &.inactive { + opacity: 0.42; + .legend-dot-fasting, + .legend-dot-postprandial { + background: #cbd5e1; + } + } + &:active { + opacity: 0.72; + } } .legend-dot { width: 16rpx; @@ -4003,6 +4032,7 @@ async function onFamilyLike() { display: flex; align-items: flex-end; justify-content: center; + animation: input-modal-mask-in 0.38s cubic-bezier(0.22, 1, 0.36, 1) both; } .input-modal { width: 100%; @@ -4014,13 +4044,22 @@ async function onFamilyLike() { max-height: 88vh; display: flex; flex-direction: column; - animation: input-modal-rise 0.28s cubic-bezier(0.16, 1, 0.3, 1); + animation: input-modal-rise 0.46s cubic-bezier(0.22, 1, 0.36, 1) both; position: relative; z-index: 1000; + will-change: transform, opacity; +} +@keyframes input-modal-mask-in { + from { opacity: 0; } + to { opacity: 1; } } @keyframes input-modal-rise { - from { transform: translateY(60rpx); opacity: 0.5; } - to { transform: translateY(0); opacity: 1; } + from { transform: translate3d(0, 100%, 0); opacity: 0.96; } + to { transform: translate3d(0, 0, 0); opacity: 1; } +} +@keyframes input-modal-content-in { + from { opacity: 0; transform: translate3d(0, 24rpx, 0); } + to { opacity: 1; transform: translate3d(0, 0, 0); } } .input-modal-grip { width: 80rpx; @@ -4072,19 +4111,27 @@ async function onFamilyLike() { font-weight: 700; } .input-modal-loading { - padding: 80rpx 0; + min-height: 520rpx; + padding: 120rpx 0; text-align: center; color: var(--slate-600); font-size: 30rpx; + display: flex; + align-items: center; + justify-content: center; } .input-modal-body { flex: 1; + min-height: 520rpx; padding: 20rpx 32rpx 28rpx; overflow-y: auto; overflow-x: hidden; box-sizing: border-box; width: 100%; } +.input-modal-body-ready { + animation: input-modal-content-in 0.34s cubic-bezier(0.22, 1, 0.36, 1) both; +} .input-modal-tip { background: var(--primary-light); border: 1rpx dashed #99f6e4; diff --git a/TUICallKit-Vue3/tongji/pages/more.vue b/TUICallKit-Vue3/tongji/pages/more.vue index 36342880..d6b225de 100644 --- a/TUICallKit-Vue3/tongji/pages/more.vue +++ b/TUICallKit-Vue3/tongji/pages/more.vue @@ -82,8 +82,8 @@ {{ todayChecked ? '今日已完成记录' : '今日还没有记录' }} - - 去记血糖 + + {{ todayChecked ? '编辑血糖' : '去记血糖' }} @@ -173,7 +173,7 @@ @@ -501,6 +501,104 @@ 数据每日同步 · 阈值仅作参考,请遵医嘱 + + + + + + + {{ inputForm.id ? '修改今日血糖' : '录入今日血糖' }} + {{ todayText }} · {{ patientName || '本人' }} + + + × + + + + 加载今日数据中… + + + + 请如实填写,留空表示该项不上传。当天可多次修改。 + + 血糖(mmol/L) + + + + 空腹血糖 + + + + + + + + + 餐后血糖 + + + + + + + + + 其他血糖 + + + + + + 备注 + +