diff --git a/apps/miniprogram/native/pkg-veepoo/index.js b/apps/miniprogram/native/pkg-veepoo/index.js
index 141c97e..ef2112a 100644
--- a/apps/miniprogram/native/pkg-veepoo/index.js
+++ b/apps/miniprogram/native/pkg-veepoo/index.js
@@ -71,6 +71,12 @@ Page({
measureError: '',
results: {},
hasResults: false,
+ // 自动测量状态
+ autoMeasuring: false,
+ autoMeasureDone: false,
+ autoMeasureStatus: {},
+ autoMeasureValues: {},
+ autoMeasureProgress: 0,
},
_authTimer: null,
@@ -84,6 +90,8 @@ Page({
_eventChannel: null,
_connecting: false,
_listenersRegistered: false,
+ _autoQueue: null,
+ _autoQueueIndex: 0,
// ── 生命周期 ──
@@ -278,6 +286,9 @@ Page({
// 认证成功后自动读取 3 天睡眠数据 + 开启自动测量
this._readSleepData();
this._enableAutoMeasurement();
+
+ // 自动依次测量所有指标(面向中老年人,减少操作)
+ this._startAutoMeasureQueue();
},
// ── SDK 事件路由 ──
@@ -415,6 +426,13 @@ Page({
// ── 测量事件处理 ──
_handleMeasureEvent: function (type, data) {
+ // 自动测量模式下,路由到自动测量处理器
+ if (this.data.autoMeasuring) {
+ this._handleAutoMeasureEvent(type, data);
+ return;
+ }
+
+ // 手动测量模式
if (this.data.selectedType !== type || this.data.measurePhase !== 'measuring') return;
var content = data.content || {};
@@ -634,4 +652,212 @@ Page({
console.warn('[veepoo-native] 开启体温自动监测失败:', e);
}
},
+
+ // ── 自动测量队列 ──
+
+ _startAutoMeasureQueue: function () {
+ var types = [];
+ var status = {};
+ for (var i = 0; i < MEASURE_TYPES.length; i++) {
+ types.push(MEASURE_TYPES[i].type);
+ status[MEASURE_TYPES[i].type] = 'pending';
+ }
+
+ this._autoQueue = types;
+ this._autoQueueIndex = 0;
+
+ this.setData({
+ autoMeasuring: true,
+ autoMeasureDone: false,
+ autoMeasureStatus: status,
+ autoMeasureValues: {},
+ autoMeasureProgress: 0,
+ });
+
+ // eslint-disable-next-line no-undef
+ console.log('[veepoo-native] 启动自动测量队列,共 ' + types.length + ' 项');
+
+ var self = this;
+ setTimeout(function () {
+ self._startNextAutoMeasure();
+ }, 800);
+ },
+
+ _startNextAutoMeasure: function () {
+ if (!this._autoQueue || this._autoQueueIndex >= this._autoQueue.length) {
+ this._onAutoMeasureComplete();
+ return;
+ }
+
+ var type = this._autoQueue[this._autoQueueIndex];
+ this._updateSelectedDisplay(type);
+
+ var status = Object.assign({}, this.data.autoMeasureStatus);
+ status[type] = 'measuring';
+ this.setData({
+ autoMeasureStatus: status,
+ measurePhase: 'measuring',
+ measureProgress: 0,
+ measureDisplayValue: '',
+ measureError: '',
+ });
+
+ // eslint-disable-next-line no-undef
+ console.log('[veepoo-native] 自动测量 [' + (this._autoQueueIndex + 1) + '/' + this._autoQueue.length + ']: ' + type);
+
+ this._lastValues = null;
+ this._sendMeasureCommand(type, true);
+
+ var self = this;
+ var timeout = MEASURE_TIMEOUTS[type] || 60000;
+ this._measureTimer = setTimeout(function () {
+ // eslint-disable-next-line no-undef
+ console.warn('[veepoo-native] 自动测量超时: ' + type);
+ self._onAutoMeasureError(type, '测量超时');
+ }, timeout);
+ },
+
+ _handleAutoMeasureEvent: function (type, data) {
+ if (!this._autoQueue || this._autoQueueIndex >= this._autoQueue.length) return;
+ if (type !== this._autoQueue[this._autoQueueIndex]) return;
+
+ var content = data.content || {};
+ var self = this;
+
+ if (content.deviceBusy === true) { self._onAutoMeasureError(type, '设备正忙'); return; }
+ if (content.notWear === true || data.state === 6) { self._onAutoMeasureError(type, '未佩戴'); return; }
+ if (data.state === 7) { self._onAutoMeasureError(type, '设备充电中'); return; }
+ if (data.state === 8) { self._onAutoMeasureError(type, '电量不足'); return; }
+ if (type === 'pressure' && data.ack === 2) { self._onAutoMeasureError(type, '电量不足'); return; }
+ if (type === 'pressure' && data.ack === 3) { self._onAutoMeasureError(type, '设备正忙'); return; }
+ if (type === 'pressure' && data.ack === 4) { self._onAutoMeasureError(type, '未佩戴'); return; }
+
+ var values = self._extractValues(type, content);
+ if (!values) return;
+
+ self._lastValues = values;
+
+ var progress = data.Progress !== undefined ? data.Progress : 0;
+ self.setData({ measureProgress: Math.max(progress, 0) });
+
+ if (progress >= 100) {
+ self._onAutoMeasureSuccess(type, values);
+ return;
+ }
+
+ if (!self._settleTimer) {
+ self._settleTimer = setTimeout(function () {
+ if (self._lastValues && self.data.autoMeasuring) {
+ self._onAutoMeasureSuccess(type, self._lastValues);
+ }
+ }, MEASURE_SETTLE_DELAY);
+ }
+ },
+
+ _onAutoMeasureSuccess: function (type, values) {
+ this._cancelPendingMeasure();
+
+ var result = { type: type, values: values, measuredAt: Date.now() };
+ var newResults = Object.assign({}, this.data.results);
+ newResults[type] = result;
+
+ var status = Object.assign({}, this.data.autoMeasureStatus);
+ status[type] = 'done';
+
+ var newValues = Object.assign({}, this.data.autoMeasureValues);
+ newValues[type] = this._formatValues(type, values);
+
+ var doneCount = 0;
+ var keys = Object.keys(status);
+ for (var i = 0; i < keys.length; i++) {
+ if (status[keys[i]] === 'done' || status[keys[i]] === 'error') doneCount++;
+ }
+ var progress = Math.round((doneCount / this._autoQueue.length) * 100);
+
+ // eslint-disable-next-line no-undef
+ console.log('[veepoo-native] 自动测量完成: ' + type + ' = ' + newValues[type] + ' (' + progress + '%)');
+
+ this.setData({
+ results: newResults,
+ hasResults: true,
+ autoMeasureStatus: status,
+ autoMeasureValues: newValues,
+ autoMeasureProgress: progress,
+ measurePhase: 'idle',
+ });
+
+ this._autoQueueIndex++;
+ var self = this;
+ setTimeout(function () {
+ self._startNextAutoMeasure();
+ }, 800);
+ },
+
+ _onAutoMeasureError: function (type, msg) {
+ this._cancelPendingMeasure();
+
+ var status = Object.assign({}, this.data.autoMeasureStatus);
+ status[type] = 'error';
+
+ var doneCount = 0;
+ var keys = Object.keys(status);
+ for (var i = 0; i < keys.length; i++) {
+ if (status[keys[i]] === 'done' || status[keys[i]] === 'error') doneCount++;
+ }
+ var progress = Math.round((doneCount / this._autoQueue.length) * 100);
+
+ // eslint-disable-next-line no-undef
+ console.warn('[veepoo-native] 自动测量失败: ' + type + ' - ' + msg + ' (' + progress + '%)');
+
+ this.setData({
+ autoMeasureStatus: status,
+ autoMeasureProgress: progress,
+ measurePhase: 'idle',
+ });
+
+ this._autoQueueIndex++;
+ var self = this;
+ setTimeout(function () {
+ self._startNextAutoMeasure();
+ }, 500);
+ },
+
+ _onAutoMeasureComplete: function () {
+ // eslint-disable-next-line no-undef
+ console.log('[veepoo-native] 自动测量全部完成');
+
+ var results = this.data.results;
+ if (Object.keys(results).length > 0) {
+ try {
+ // eslint-disable-next-line no-undef
+ wx.setStorageSync('hms:veepoo_measure_results', JSON.stringify(results));
+ } catch (_) { /* ignore */ }
+ }
+
+ this.setData({
+ autoMeasureDone: true,
+ autoMeasuring: false,
+ autoMeasureProgress: 100,
+ measurePhase: 'idle',
+ });
+ },
+
+ handleCancelAutoMeasure: function () {
+ this._cancelPendingMeasure();
+ this._autoQueue = null;
+
+ var results = this.data.results;
+ if (Object.keys(results).length > 0) {
+ try {
+ // eslint-disable-next-line no-undef
+ wx.setStorageSync('hms:veepoo_measure_results', JSON.stringify(results));
+ } catch (_) { /* ignore */ }
+ }
+
+ this.setData({
+ autoMeasuring: false,
+ autoMeasureDone: false,
+ measurePhase: 'idle',
+ });
+ },
});
diff --git a/apps/miniprogram/native/pkg-veepoo/index.wxml b/apps/miniprogram/native/pkg-veepoo/index.wxml
index 73f78b3..b332021 100644
--- a/apps/miniprogram/native/pkg-veepoo/index.wxml
+++ b/apps/miniprogram/native/pkg-veepoo/index.wxml
@@ -48,7 +48,78 @@
-
+
+
+
+
+
+
+
+ {{deviceName}}
+ {{batteryLevel}}%
+
+ 取消
+
+
+
+
+
+
+
+
+
+
+
+ {{autoMeasureStatus[item.type] === 'done' ? '✓' : autoMeasureStatus[item.type] === 'error' ? '✕' : item.icon}}
+
+ {{item.label}}
+
+
+
+ {{autoMeasureValues[item.type]}}
+ {{item.unit}}
+
+ 测量中...
+ 已跳过
+ 等待中
+
+
+
+
+
+
+
+
+
+ {{autoMeasureProgress}}%
+
+
+
+
+ 测量数据仅供参考,不作为医学诊断依据。如有不适请及时就医。
+
+
+
+
+
+ 查看结果并返回
+
+
+ 取消自动测量
+
+
+
+
+
+
+
diff --git a/apps/miniprogram/native/pkg-veepoo/index.wxss b/apps/miniprogram/native/pkg-veepoo/index.wxss
index 0ae178b..dda3eb5 100644
--- a/apps/miniprogram/native/pkg-veepoo/index.wxss
+++ b/apps/miniprogram/native/pkg-veepoo/index.wxss
@@ -111,6 +111,161 @@ page {
/* ═══════════════════════════════════════
测量页面(就绪态)
═══════════════════════════════════════ */
+
+/* ═══ 自动测量进度 ═══ */
+.auto-measure {
+ padding: 24px 20px 40px;
+}
+
+.auto-measure__header {
+ text-align: center;
+ margin-bottom: 28px;
+}
+
+.auto-measure__title {
+ display: block;
+ font-family: Georgia, 'Times New Roman', serif;
+ font-size: 24px;
+ font-weight: 700;
+ color: var(--tx);
+ margin-bottom: 8px;
+}
+
+.auto-measure__subtitle {
+ display: block;
+ font-size: 14px;
+ color: var(--tx3);
+}
+
+.auto-measure__list {
+ background: var(--card);
+ border-radius: 16px;
+ box-shadow: 0 2px 12px rgba(45,42,38,0.06);
+ overflow: hidden;
+}
+
+.auto-item {
+ display: flex;
+ align-items: center;
+ justify-content: space-between;
+ padding: 16px 20px;
+ border-bottom: 1px solid var(--bd);
+ transition: background 200ms ease;
+}
+
+.auto-item:last-child {
+ border-bottom: none;
+}
+
+.auto-item--active {
+ background: rgba(196,98,58,0.04);
+}
+
+.auto-item--done {
+ background: rgba(91,122,94,0.04);
+}
+
+.auto-item--error {
+ opacity: 0.6;
+}
+
+.auto-item__left {
+ display: flex;
+ align-items: center;
+ gap: 14px;
+}
+
+.auto-item__icon-wrap {
+ width: 40px;
+ height: 40px;
+ border-radius: 12px;
+ display: flex;
+ align-items: center;
+ justify-content: center;
+}
+
+.auto-item--done .auto-item__icon-wrap {
+ background: var(--acc) !important;
+}
+
+.auto-item--error .auto-item__icon-wrap {
+ background: var(--tx3) !important;
+}
+
+.auto-item__icon {
+ font-size: 18px;
+ color: #fff;
+ font-weight: 700;
+}
+
+.auto-item__label {
+ font-size: 16px;
+ font-weight: 600;
+ color: var(--tx);
+}
+
+.auto-item__right {
+ display: flex;
+ align-items: baseline;
+ gap: 4px;
+}
+
+.auto-item__value {
+ font-family: Georgia, 'Times New Roman', serif;
+ font-size: 22px;
+ font-weight: 700;
+}
+
+.auto-item__unit {
+ font-size: 13px;
+ color: var(--tx3);
+}
+
+.auto-item__status {
+ font-size: 14px;
+ color: var(--tx3);
+}
+
+.auto-item__status--active {
+ color: var(--pri);
+ font-weight: 600;
+}
+
+.auto-item__status--error {
+ color: var(--tx3);
+}
+
+/* ── 自动测量进度条 ── */
+.auto-progress {
+ display: flex;
+ align-items: center;
+ gap: 12px;
+ margin-top: 24px;
+ padding: 0 4px;
+}
+
+.auto-progress__bar {
+ flex: 1;
+ height: 6px;
+ background: var(--bd);
+ border-radius: 3px;
+ overflow: hidden;
+}
+
+.auto-progress__fill {
+ height: 100%;
+ background: var(--pri);
+ border-radius: 3px;
+ transition: width 0.5s ease-out;
+}
+
+.auto-progress__text {
+ font-size: 14px;
+ font-weight: 600;
+ color: var(--pri);
+ min-width: 36px;
+ text-align: right;
+}
.measure-page {
min-height: 100vh;
padding-bottom: 40px;
@@ -279,6 +434,8 @@ page {
flex-direction: column;
align-items: center;
justify-content: center;
+ background: var(--bg);
+ border-radius: 50%;
}
.gauge__icon-lg {