Files
cmr-mini/miniprogram/pages/map/map.wxml

761 lines
45 KiB
Plaintext
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<view class="page">
<view
class="app-edge-glow app-edge-glow--{{panelTelemetryTone}}"
wx:if="{{panelTelemetryTone === 'orange' || panelTelemetryTone === 'red'}}"
></view>
<view
class="map-stage"
catchtouchstart="handleTouchStart"
catchtouchmove="handleTouchMove"
catchtouchend="handleTouchEnd"
catchtouchcancel="handleTouchCancel"
>
<view class="map-content">
<canvas
id="mapCanvas"
type="webgl"
canvas-id="mapCanvas"
class="map-canvas map-canvas--base"
></canvas>
<canvas
id="routeLabelCanvas"
type="2d"
canvas-id="routeLabelCanvas"
class="map-canvas map-canvas--labels"
></canvas>
</view>
<view class="map-stage__map-pulse {{mapPulseFxClass}}" wx:if="{{mapPulseVisible}}" style="left: {{mapPulseLeftPx}}px; top: {{mapPulseTopPx}}px;"></view>
<view class="map-stage__stage-fx {{stageFxClass}}" wx:if="{{stageFxVisible}}"></view>
<view class="game-punch-feedback game-punch-feedback--{{punchFeedbackTone}} {{punchFeedbackFxClass}}" wx:if="{{punchFeedbackVisible}}">{{punchFeedbackText}}</view>
<view class="game-content-card {{contentCardFxClass}}" wx:if="{{contentCardVisible}}" bindtap="handleCloseContentCard">
<view class="game-content-card__title">{{contentCardTitle}}</view>
<view class="game-content-card__body">{{contentCardBody}}</view>
<view class="game-content-card__hint">点击关闭</view>
</view>
<view class="map-stage__overlay-center-layer" wx:if="{{!showDebugPanel && !showGameInfoPanel && !showSystemSettingsPanel}}">
<view class="center-scale-ruler" wx:if="{{centerScaleRulerVisible}}" style="left: {{centerScaleRulerCenterXPx}}px; top: {{centerScaleRulerZeroYPx}}px; height: {{centerScaleRulerHeightPx}}px;">
<view class="center-scale-ruler__axis" style="bottom: {{centerScaleRulerAxisBottomPx}}px;"></view>
<view class="center-scale-ruler__arrow"></view>
<view wx:if="{{centerScaleRulerZeroVisible}}" class="center-scale-ruler__tick center-scale-ruler__tick--major center-scale-ruler__tick--zero" style="top: {{centerScaleRulerHeightPx}}px;"></view>
<view wx:if="{{centerScaleRulerZeroVisible}}" class="center-scale-ruler__label center-scale-ruler__label--zero" style="top: {{centerScaleRulerHeightPx}}px;">{{centerScaleRulerZeroLabel}}</view>
<view wx:for="{{centerScaleRulerMinorTicks}}" wx:key="key" class="center-scale-ruler__tick {{item.long ? 'center-scale-ruler__tick--major' : ''}}" style="top: {{item.topPx}}px;"></view>
<view wx:for="{{centerScaleRulerMajorMarks}}" wx:key="key" class="center-scale-ruler__label" style="top: {{item.topPx}}px;">{{item.label}}</view>
</view>
</view>
<view class="map-stage__overlay">
<view class="map-stage__bottom">
<view class="compass-widget">
<view class="compass-widget__heading-wrap">
<view class="compass-widget__heading">{{sensorHeadingText}}</view>
<view class="compass-widget__edge-arrow-wrap">
<view class="compass-widget__edge-arrow"></view>
</view>
</view>
<view class="compass-widget__dial {{orientationMode === 'heading-up' ? 'compass-widget__dial--active' : ''}}">
<view class="compass-widget__glass"></view>
<view class="compass-widget__inner-shadow"></view>
<view class="compass-widget__card" style="transform: rotate({{rotationDeg}}deg);">
<image class="compass-widget__north-arrow" src="../../assets/compass-north-arrow.svg" mode="aspectFit"></image>
<view wx:for="{{compassTicks}}" wx:key="angle" class="compass-widget__tick-anchor" style="transform: translate(-50%, -50%) rotate({{item.angle}}deg);">
<view class="compass-widget__tick {{item.long ? 'compass-widget__tick--long' : 'compass-widget__tick--short'}} {{item.major ? 'compass-widget__tick--major' : ''}}"></view>
</view>
<view wx:for="{{compassLabels}}" wx:key="text" class="compass-widget__mark-anchor" style="transform: translate(-50%, -50%) rotate({{item.angle}}deg);">
<view class="compass-widget__mark {{item.className}}" style="transform: translate(-50%, -50%) translateY(-{{item.radius}}rpx) rotate({{item.rotateBack}}deg);">{{item.text}}</view>
</view>
</view>
<view class="compass-widget__needle-anchor" style="transform: translate(-50%, -50%) rotate({{compassNeedleDeg}}deg);">
<view class="compass-widget__needle-north"></view>
<view class="compass-widget__needle-south"></view>
</view>
<view class="compass-widget__hub"></view>
<view class="compass-widget__hub-core"></view>
</view>
<view class="compass-widget__hint" wx:if="{{compassDeclinationText}}">{{compassDeclinationText}}</view>
</view>
</view>
</view>
</view>
<view class="game-punch-hint" wx:if="{{showPunchHintBanner && punchHintText}}" style="top: {{topInsetHeight}}px;" catchtouchstart="handlePunchHintTap" catchtouchmove="handlePunchHintTap" catchtouchend="handlePunchHintTap">
<view class="game-punch-hint__text">{{punchHintText}}</view>
<view class="game-punch-hint__close" catchtouchstart="handlePunchHintTap" catchtouchmove="handlePunchHintTap" catchtouchend="handlePunchHintTap" catchtap="handleClosePunchHint">×</view>
</view>
<cover-view class="map-side-toggle" wx:if="{{!showDebugPanel && !showGameInfoPanel && !showSystemSettingsPanel}}" style="top: {{topInsetHeight}}px;" bindtap="handleCycleSideButtons">
<cover-view class="map-side-button map-side-button--icon">
<cover-image class="map-side-button__image" src="{{sideToggleIconSrc}}"></cover-image>
</cover-view>
</cover-view>
<cover-view class="map-side-column map-side-column--left map-side-column--left-group" wx:if="{{!showDebugPanel && !showGameInfoPanel && !showSystemSettingsPanel && showLeftButtonGroup}}" style="top: {{topInsetHeight}}px;">
<cover-view class="map-side-button map-side-button--icon" bindtap="handleToggleMapRotateMode"><cover-image class="map-side-button__rotate-image {{orientationMode === 'heading-up' ? 'map-side-button__rotate-image--active' : ''}}" src="../../assets/btn_map_rotate_cropped.png"></cover-image></cover-view>
<cover-view class="map-side-button map-side-button--muted"><cover-view class="map-side-button__text">1</cover-view></cover-view>
<cover-view class="{{sideButton2Class}}" bindtap="handleToggleGpsLock"><cover-view class="map-side-button__text">2</cover-view></cover-view>
<cover-view class="map-side-button map-side-button--active"><cover-view class="map-side-button__text">3</cover-view></cover-view>
<cover-view class="{{sideButton4Class}}" bindtap="handleForceExitGame"><cover-image class="map-side-button__action-image" src="../../assets/btn_exit.png"></cover-image></cover-view>
</cover-view>
<cover-view class="map-side-column map-side-column--right-main" wx:if="{{!showDebugPanel && !showGameInfoPanel && !showSystemSettingsPanel && showRightButtonGroups}}" style="top: {{topInsetHeight}}px;">
<cover-view class="map-side-button"><cover-view class="map-side-button__text">5</cover-view></cover-view>
<cover-view class="map-side-button map-side-button--active"><cover-view class="map-side-button__text">6</cover-view></cover-view>
<cover-view class="map-side-button"><cover-view class="map-side-button__text">7</cover-view></cover-view>
<cover-view class="map-side-button map-side-button--active"><cover-view class="map-side-button__text">8</cover-view></cover-view>
<cover-view class="map-side-button map-side-button--muted"><cover-view class="map-side-button__text">9</cover-view></cover-view>
<cover-view class="map-side-button map-side-button--active"><cover-view class="map-side-button__text">10</cover-view></cover-view>
</cover-view>
<cover-view class="map-side-column map-side-column--right-sub" wx:if="{{!showDebugPanel && !showGameInfoPanel && !showSystemSettingsPanel && showRightButtonGroups}}" style="top: {{topInsetHeight}}px;">
<cover-view class="{{sideButton11Class}}" bindtap="handleOpenGameInfoPanel"><cover-image class="map-side-button__action-image" src="../../assets/btn_info.png"></cover-image></cover-view>
<cover-view class="{{sideButton12Class}}" bindtap="handleOpenSystemSettingsPanel"><cover-view class="map-side-button__text">12</cover-view></cover-view>
<cover-view class="map-side-button"><cover-view class="map-side-button__text">13</cover-view></cover-view>
<cover-view class="map-side-button"><cover-view class="map-side-button__text">14</cover-view></cover-view>
<cover-view class="map-side-button"><cover-view class="map-side-button__text">15</cover-view></cover-view>
<cover-view class="{{sideButton16Class}}" bindtap="handleSkipAction"><cover-image class="map-side-button__action-image" src="../../assets/btn_skip_cp.png"></cover-image></cover-view>
</cover-view>
<cover-view class="map-punch-button {{punchButtonEnabled ? 'map-punch-button--active' : ''}} {{punchButtonFxClass}}" wx:if="{{!showDebugPanel && !showGameInfoPanel && !showSystemSettingsPanel}}" bindtap="handlePunchAction">
<cover-view class="map-punch-button__text">{{punchButtonText}}</cover-view>
</cover-view>
<cover-view class="screen-button-layer screen-button-layer--start-left" wx:if="{{!showDebugPanel && !showGameInfoPanel && !showSystemSettingsPanel && showBottomDebugButton && gameSessionStatus === 'idle'}}" bindtap="handleStartGame">
<cover-view class="screen-button-layer__text screen-button-layer__text--start">开始</cover-view>
</cover-view>
<cover-view class="screen-button-layer screen-button-layer--bottom-left" wx:if="{{!showDebugPanel && !showGameInfoPanel && !showSystemSettingsPanel && showBottomDebugButton}}" bindtap="handleToggleDebugPanel">
<cover-view class="screen-button-layer__icon">
<cover-view class="screen-button-layer__line"></cover-view>
<cover-view class="screen-button-layer__stand"></cover-view>
</cover-view>
<cover-view class="screen-button-layer__text">调试</cover-view>
</cover-view>
<swiper wx:if="{{!showGameInfoPanel && !showSystemSettingsPanel}}" class="race-panel-swiper" current="{{hudPanelIndex}}" bindchange="handleHudPanelChange" duration="220" easing-function="easeOutCubic">
<swiper-item>
<view class="race-panel race-panel--tone-{{panelTelemetryTone}}">
<view class="race-panel__tag race-panel__tag--top-left">{{panelActionTagText}}</view>
<view class="race-panel__tag race-panel__tag--top-right">里程</view>
<view class="race-panel__tag race-panel__tag--bottom-left">{{panelDistanceTagText}}</view>
<view class="race-panel__tag race-panel__tag--bottom-right">速度</view>
<view class="race-panel__line race-panel__line--center"></view>
<view class="race-panel__line race-panel__line--left-mid"></view>
<view class="race-panel__line race-panel__line--right-mid"></view>
<view class="race-panel__line race-panel__line--left-top"></view>
<view class="race-panel__line race-panel__line--left-bottom"></view>
<view class="race-panel__line race-panel__line--right-top"></view>
<view class="race-panel__line race-panel__line--right-bottom"></view>
<view class="race-panel__grid">
<view class="race-panel__cell race-panel__cell--action">
<view class="race-panel__action-button"><!-- status only -->
<view class="race-panel__action-button-text">{{punchButtonText}}</view>
</view>
</view>
<view class="race-panel__cell race-panel__cell--timer">
<text class="race-panel__timer {{panelTimerFxClass}}">{{panelTimerText}}</text>
</view>
<view class="race-panel__cell race-panel__cell--mileage">
<view class="race-panel__mileage-wrap {{panelMileageFxClass}}">
<text class="race-panel__mileage">{{panelMileageText}}</text>
<view class="race-panel__chevrons">
<view class="race-panel__chevron"></view>
<view class="race-panel__chevron race-panel__chevron--offset"></view>
</view>
</view>
</view>
<view class="race-panel__cell race-panel__cell--distance">
<view class="race-panel__metric-group race-panel__metric-group--left {{panelDistanceFxClass}}">
<text class="race-panel__metric-value race-panel__metric-value--distance">{{panelDistanceValueText}}</text>
<text class="race-panel__metric-unit race-panel__metric-unit--distance">{{panelDistanceUnitText}}</text>
</view>
</view>
<view class="race-panel__cell race-panel__cell--progress">
<text class="race-panel__progress {{panelProgressFxClass}}">{{panelProgressText}}</text>
</view>
<view class="race-panel__cell race-panel__cell--speed">
<view class="race-panel__metric-group race-panel__metric-group--right {{panelSpeedFxClass}}">
<text class="race-panel__metric-value race-panel__metric-value--speed">{{panelSpeedValueText}}</text>
<text class="race-panel__metric-unit race-panel__metric-unit--speed">km/h</text>
</view>
</view>
</view>
</view>
</swiper-item>
<swiper-item>
<view class="race-panel race-panel--tone-{{panelTelemetryTone}}">
<view class="race-panel__tag race-panel__tag--top-left">心率</view>
<view class="race-panel__tag race-panel__tag--top-right">卡路里</view>
<view class="race-panel__tag race-panel__tag--bottom-left">均速</view>
<view class="race-panel__tag race-panel__tag--bottom-right">精度</view>
<view class="race-panel__line race-panel__line--center"></view>
<view class="race-panel__line race-panel__line--left-mid"></view>
<view class="race-panel__line race-panel__line--right-mid"></view>
<view class="race-panel__line race-panel__line--left-top"></view>
<view class="race-panel__line race-panel__line--left-bottom"></view>
<view class="race-panel__line race-panel__line--right-top"></view>
<view class="race-panel__line race-panel__line--right-bottom"></view>
<view class="race-panel__grid">
<view class="race-panel__cell race-panel__cell--action">
<view class="race-panel__metric-group race-panel__metric-group--left race-panel__metric-group--panel {{panelHeartRateFxClass}}">
<text class="race-panel__metric-value race-panel__metric-value--telemetry">{{panelHeartRateValueText}}</text>
<text class="race-panel__metric-unit race-panel__metric-unit--telemetry">{{panelHeartRateUnitText}}</text>
</view>
</view>
<view class="race-panel__cell race-panel__cell--timer">
<text class="race-panel__timer {{panelTimerFxClass}}">{{panelTimerText}}</text>
</view>
<view class="race-panel__cell race-panel__cell--mileage">
<view class="race-panel__metric-group race-panel__metric-group--right race-panel__metric-group--panel">
<text class="race-panel__metric-value race-panel__metric-value--telemetry">{{panelCaloriesValueText}}</text>
<text class="race-panel__metric-unit race-panel__metric-unit--telemetry">{{panelCaloriesUnitText}}</text>
</view>
</view>
<view class="race-panel__cell race-panel__cell--distance">
<view class="race-panel__metric-group race-panel__metric-group--left race-panel__metric-group--panel">
<text class="race-panel__metric-value race-panel__metric-value--telemetry-secondary">{{panelAverageSpeedValueText}}</text>
<text class="race-panel__metric-unit race-panel__metric-unit--telemetry">{{panelAverageSpeedUnitText}}</text>
</view>
</view>
<view class="race-panel__cell race-panel__cell--progress">
<view class="race-panel__zone">
<text class="race-panel__zone-name">{{panelHeartRateZoneNameText}}</text>
<text class="race-panel__zone-range">{{panelHeartRateZoneRangeText}}</text>
</view>
</view>
<view class="race-panel__cell race-panel__cell--speed">
<view class="race-panel__metric-group race-panel__metric-group--right race-panel__metric-group--panel">
<text class="race-panel__metric-value race-panel__metric-value--telemetry-secondary">{{panelAccuracyValueText}}</text>
<text class="race-panel__metric-unit race-panel__metric-unit--telemetry">{{panelAccuracyUnitText}}</text>
</view>
</view>
</view>
</view>
</swiper-item>
</swiper>
<view class="race-panel-pager" wx:if="{{!showDebugPanel && !showGameInfoPanel && !showSystemSettingsPanel}}">
<view class="race-panel-pager__dot {{hudPanelIndex === 0 ? 'race-panel-pager__dot--active' : ''}}"></view>
<view class="race-panel-pager__dot {{hudPanelIndex === 1 ? 'race-panel-pager__dot--active' : ''}}"></view>
</view>
<view class="game-info-modal" wx:if="{{showGameInfoPanel}}" bindtap="handleCloseGameInfoPanel">
<view class="game-info-modal__dialog" catchtap="handleGameInfoPanelTap">
<view class="game-info-modal__header">
<view class="game-info-modal__header-main">
<view class="game-info-modal__eyebrow">GAME INFO</view>
<view class="game-info-modal__title">{{gameInfoTitle}}</view>
<view class="game-info-modal__subtitle">{{gameInfoSubtitle}}</view>
</view>
<view class="game-info-modal__header-actions">
<view class="game-info-modal__close" bindtap="handleCloseGameInfoPanel">关闭</view>
</view>
</view>
<scroll-view class="game-info-modal__content" scroll-y enhanced show-scrollbar="true">
<view class="debug-section debug-section--info">
<view class="debug-section__header">
<view class="debug-section__title">Local</view>
<view class="debug-section__desc">当前设备、本地玩法与实时运行状态</view>
</view>
<view class="info-panel__row" wx:for="{{gameInfoLocalRows}}" wx:key="label">
<text class="info-panel__label">{{item.label}}</text>
<text class="info-panel__value">{{item.value}}</text>
</view>
</view>
<view class="debug-section debug-section--info">
<view class="debug-section__header">
<view class="debug-section__title">Global</view>
<view class="debug-section__desc">联网后接入全局赛事数据,这里先占位</view>
</view>
<view class="info-panel__row" wx:for="{{gameInfoGlobalRows}}" wx:key="label">
<text class="info-panel__label">{{item.label}}</text>
<text class="info-panel__value">{{item.value}}</text>
</view>
</view>
</scroll-view>
</view>
</view>
<view class="game-info-modal" wx:if="{{showSystemSettingsPanel}}" bindtap="handleCloseSystemSettingsPanel">
<view class="game-info-modal__dialog" catchtap="handleSystemSettingsPanelTap">
<view class="game-info-modal__header">
<view class="game-info-modal__header-main">
<view class="game-info-modal__eyebrow">SYSTEM SETTINGS</view>
<view class="game-info-modal__title">系统设置</view>
<view class="game-info-modal__subtitle">用户端偏好与设备级选项</view>
</view>
<view class="game-info-modal__header-actions">
<view class="game-info-modal__close" bindtap="handleCloseSystemSettingsPanel">关闭</view>
</view>
</view>
<scroll-view class="game-info-modal__content" scroll-y enhanced show-scrollbar="true">
<view class="debug-section debug-section--info">
<view class="debug-section__header">
<view class="debug-section__title">01. 动画性能</view>
<view class="debug-section__desc">根据设备性能切换动画强度,低端机建议精简</view>
</view>
<view class="info-panel__row">
<text class="info-panel__label">当前级别</text>
<text class="info-panel__value">{{animationLevel === 'lite' ? '精简' : '标准'}}</text>
</view>
<view class="control-row">
<view class="control-chip {{animationLevel === 'standard' ? 'control-chip--active' : 'control-chip--secondary'}}" bindtap="handleSetAnimationLevelStandard">标准</view>
<view class="control-chip {{animationLevel === 'lite' ? 'control-chip--active' : 'control-chip--secondary'}}" bindtap="handleSetAnimationLevelLite">精简</view>
</view>
</view>
<view class="debug-section debug-section--info">
<view class="debug-section__header">
<view class="debug-section__title">02. 比例尺显示</view>
<view class="debug-section__desc">控制比例尺显示与否,默认沿用你的本地偏好</view>
</view>
<view class="info-panel__row">
<text class="info-panel__label">当前状态</text>
<text class="info-panel__value">{{showCenterScaleRuler ? '显示' : '隐藏'}}</text>
</view>
<view class="control-row">
<view class="control-chip {{showCenterScaleRuler ? 'control-chip--active' : 'control-chip--secondary'}}" bindtap="handleSetCenterScaleRulerVisibleOn">显示</view>
<view class="control-chip {{!showCenterScaleRuler ? 'control-chip--active' : 'control-chip--secondary'}}" bindtap="handleSetCenterScaleRulerVisibleOff">隐藏</view>
</view>
</view>
<view class="debug-section debug-section--info">
<view class="debug-section__header">
<view class="debug-section__title">03. 比例尺基准点</view>
<view class="debug-section__desc">设置比例尺零点锚定位置,可跟随屏幕中心或指北针圆心</view>
</view>
<view class="info-panel__row">
<text class="info-panel__label">当前锚点</text>
<text class="info-panel__value">{{centerScaleRulerAnchorMode === 'compass-center' ? '指北针圆心' : '屏幕中心'}}</text>
</view>
<view class="control-row">
<view class="control-chip {{centerScaleRulerAnchorMode === 'screen-center' ? 'control-chip--active' : 'control-chip--secondary'}}" bindtap="handleSetCenterScaleRulerAnchorScreenCenter">屏幕中心</view>
<view class="control-chip {{centerScaleRulerAnchorMode === 'compass-center' ? 'control-chip--active' : 'control-chip--secondary'}}" bindtap="handleSetCenterScaleRulerAnchorCompassCenter">指北针圆心</view>
</view>
</view>
<view class="debug-section debug-section--info">
<view class="debug-section__header">
<view class="debug-section__title">04. 北参考</view>
<view class="debug-section__desc">切换磁北/真北作为地图与指北针参考</view>
</view>
<view class="info-panel__row">
<text class="info-panel__label">当前参考</text>
<text class="info-panel__value">{{northReferenceText}}</text>
</view>
<view class="control-row">
<view class="control-chip {{northReferenceMode === 'magnetic' ? 'control-chip--active' : 'control-chip--secondary'}}" bindtap="handleSetNorthReferenceMagnetic">磁北</view>
<view class="control-chip {{northReferenceMode === 'true' ? 'control-chip--active' : 'control-chip--secondary'}}" bindtap="handleSetNorthReferenceTrue">真北</view>
</view>
</view>
<view class="debug-section debug-section--info">
<view class="debug-section__header">
<view class="debug-section__title">05. 心率设备</view>
<view class="debug-section__desc">清除已记住的首选心率带设备,下次重新选择</view>
</view>
<view class="control-row">
<view class="control-chip control-chip--secondary" bindtap="handleClearPreferredHeartRateDevice">清除首选设备</view>
</view>
</view>
</scroll-view>
</view>
</view>
<view class="debug-modal" wx:if="{{showDebugPanel}}" bindtap="handleCloseDebugPanel">
<view class="debug-modal__dialog" catchtap="handleDebugPanelTap">
<view class="debug-modal__header">
<view class="debug-modal__header-main">
<view class="debug-modal__eyebrow">DEBUG PANEL</view>
<view class="debug-modal__build">{{buildVersion}}</view>
</view>
<view class="debug-modal__header-actions">
<view class="debug-modal__close" bindtap="handleCloseDebugPanel">关闭</view>
</view>
</view>
<scroll-view class="debug-modal__content" scroll-y enhanced show-scrollbar="true">
<view class="debug-section">
<view class="debug-section__header">
<view class="debug-section__title">Session</view>
<view class="debug-section__desc">当前局状态与主流程控制</view>
</view>
<view class="info-panel__row">
<text class="info-panel__label">Mode</text>
<text class="info-panel__value">{{gameModeText}}</text>
</view>
<view class="info-panel__row">
<text class="info-panel__label">Config</text>
<text class="info-panel__value">{{configSourceText}}</text>
</view>
<view class="info-panel__row">
<text class="info-panel__label">Game</text>
<text class="info-panel__value">{{gameSessionStatus}}</text>
</view>
<view class="info-panel__row">
<text class="info-panel__label">Progress</text>
<text class="info-panel__value">{{panelProgressText}}</text>
</view>
<view class="info-panel__row">
<text class="info-panel__label">Timer</text>
<text class="info-panel__value">{{panelTimerText}}</text>
</view>
<view class="info-panel__row info-panel__row--stack">
<text class="info-panel__label">Punch Hint</text>
<text class="info-panel__value">{{punchHintText}}</text>
</view>
<view class="control-row">
<view class="control-chip {{configSourceText === '顺序赛配置' ? 'control-chip--active' : 'control-chip--secondary'}}" bindtap="handleLoadClassicConfig">顺序赛配置</view>
<view class="control-chip {{configSourceText === '积分赛配置' ? 'control-chip--active' : 'control-chip--secondary'}}" bindtap="handleLoadScoreOConfig">积分赛配置</view>
</view>
<view class="control-row">
<view class="control-chip control-chip--primary" bindtap="handleRecenter">回到首屏</view>
<view class="control-chip control-chip--secondary" bindtap="handleRotationReset">旋转归零</view>
</view>
<view class="control-row">
<view class="control-chip control-chip--secondary" bindtap="handleClearMapTestArtifacts">清空测试痕迹</view>
</view>
</view>
<view class="debug-section">
<view class="debug-section__header">
<view class="debug-section__title">Sensors</view>
<view class="debug-section__desc">定位、罗盘与心率带连接状态</view>
</view>
<view class="info-panel__row">
<text class="info-panel__label">GPS</text>
<text class="info-panel__value">{{gpsTrackingText}}</text>
</view>
<view class="info-panel__row">
<text class="info-panel__label">Location Source</text>
<text class="info-panel__value">{{locationSourceText}}</text>
</view>
<view class="info-panel__row info-panel__row--stack">
<text class="info-panel__label">GPS Coord</text>
<text class="info-panel__value">{{gpsCoordText}}</text>
</view>
<view class="info-panel__row info-panel__row--stack">
<text class="info-panel__label">Mock Bridge</text>
<text class="info-panel__value">{{mockBridgeStatusText}}</text>
</view>
<view class="info-panel__row info-panel__row--stack">
<text class="info-panel__label">Mock URL</text>
<view class="debug-inline-stack">
<input
class="debug-input"
value="{{mockBridgeUrlDraft}}"
placeholder="ws://192.168.x.x:17865/mock-gps"
bindinput="handleMockBridgeUrlInput"
/>
<view class="control-row control-row--compact">
<view class="control-chip control-chip--secondary" bindtap="handleSaveMockBridgeUrl">保存地址</view>
<view class="control-chip {{mockBridgeConnected ? 'control-chip--active' : 'control-chip--secondary'}}" bindtap="handleConnectMockLocationBridge">连接模拟源</view>
<view class="control-chip control-chip--secondary" bindtap="handleDisconnectMockLocationBridge">断开模拟源</view>
</view>
</view>
</view>
<view class="info-panel__row info-panel__row--stack">
<text class="info-panel__label">Mock Coord</text>
<text class="info-panel__value">{{mockCoordText}}</text>
</view>
<view class="info-panel__row">
<text class="info-panel__label">Mock Speed</text>
<text class="info-panel__value">{{mockSpeedText}}</text>
</view>
<view class="info-panel__row">
<text class="info-panel__label">Heart Rate</text>
<text class="info-panel__value">{{heartRateStatusText}}</text>
</view>
<view class="info-panel__row">
<text class="info-panel__label">Heart Source</text>
<text class="info-panel__value">{{heartRateSourceText}}</text>
</view>
<view class="info-panel__row info-panel__row--stack">
<text class="info-panel__label">HR Device</text>
<text class="info-panel__value">{{heartRateDeviceText}}</text>
</view>
<view class="control-row">
<view class="control-chip {{heartRateSourceMode === 'real' ? 'control-chip--active' : 'control-chip--secondary'}}" bindtap="handleSetRealHeartRateMode">真实心率</view>
<view class="control-chip {{heartRateSourceMode === 'mock' ? 'control-chip--active' : 'control-chip--secondary'}}" bindtap="handleSetMockHeartRateMode">模拟心率</view>
</view>
<view class="info-panel__row" wx:if="{{heartRateSourceMode === 'real'}}">
<text class="info-panel__label">HR Scan</text>
<text class="info-panel__value">{{heartRateScanText}}</text>
</view>
<view class="debug-device-list" wx:if="{{heartRateSourceMode === 'real' && heartRateDiscoveredDevices.length}}">
<view class="debug-device-card" wx:for="{{heartRateDiscoveredDevices}}" wx:key="deviceId">
<view class="debug-device-card__main">
<view class="debug-device-card__title-row">
<text class="debug-device-card__name">{{item.name}}</text>
<text class="debug-device-card__badge" wx:if="{{item.preferred}}">首选</text>
</view>
<text class="debug-device-card__meta">{{item.rssiText}}</text>
</view>
<view class="debug-device-card__action {{item.connected ? 'debug-device-card__action--active' : ''}}" data-device-id="{{item.deviceId}}" bindtap="handleConnectHeartRateDevice">{{item.connected ? '已连接' : '连接'}}</view>
</view>
</view>
<view class="control-row" wx:if="{{heartRateSourceMode === 'real'}}">
<view class="control-chip {{heartRateConnected ? 'control-chip--active' : 'control-chip--secondary'}}" bindtap="handleConnectHeartRate">{{heartRateConnected ? '心率带已连接' : '连接心率带'}}</view>
<view class="control-chip control-chip--secondary" bindtap="handleDisconnectHeartRate">断开心率带</view>
</view>
<view class="control-row" wx:if="{{heartRateSourceMode === 'real'}}">
<view class="control-chip control-chip--secondary" bindtap="handleClearPreferredHeartRateDevice">清除首选</view>
</view>
<view class="info-panel__row info-panel__row--stack" wx:if="{{heartRateSourceMode === 'mock'}}">
<text class="info-panel__label">Mock HR Bridge</text>
<text class="info-panel__value">{{mockHeartRateBridgeStatusText}}</text>
</view>
<view class="info-panel__row info-panel__row--stack" wx:if="{{heartRateSourceMode === 'mock'}}">
<text class="info-panel__label">Mock HR URL</text>
<view class="debug-inline-stack">
<input
class="debug-input"
value="{{mockHeartRateBridgeUrlDraft}}"
placeholder="ws://192.168.x.x:17865/mock-gps"
bindinput="handleMockHeartRateBridgeUrlInput"
/>
<view class="control-row control-row--compact">
<view class="control-chip control-chip--secondary" bindtap="handleSaveMockHeartRateBridgeUrl">保存地址</view>
<view class="control-chip {{mockHeartRateBridgeConnected ? 'control-chip--active' : 'control-chip--secondary'}}" bindtap="handleConnectMockHeartRateBridge">连接模拟心率源</view>
<view class="control-chip control-chip--secondary" bindtap="handleDisconnectMockHeartRateBridge">断开模拟心率源</view>
</view>
</view>
</view>
<view class="info-panel__row" wx:if="{{heartRateSourceMode === 'mock'}}">
<text class="info-panel__label">Mock BPM</text>
<text class="info-panel__value">{{mockHeartRateText}}</text>
</view>
<view class="info-panel__row">
<text class="info-panel__label">Heading Mode</text>
<text class="info-panel__value">{{orientationModeText}}</text>
</view>
<view class="info-panel__row">
<text class="info-panel__label">Sensor Heading</text>
<text class="info-panel__value">{{sensorHeadingText}}</text>
</view>
<view class="info-panel__row">
<text class="info-panel__label">Device Heading</text>
<text class="info-panel__value">{{deviceHeadingText}}</text>
</view>
<view class="info-panel__row">
<text class="info-panel__label">Pose</text>
<text class="info-panel__value">{{devicePoseText}}</text>
</view>
<view class="info-panel__row">
<text class="info-panel__label">Heading Confidence</text>
<text class="info-panel__value">{{headingConfidenceText}}</text>
</view>
<view class="info-panel__row">
<text class="info-panel__label">Compass Source</text>
<text class="info-panel__value">{{compassSourceText}}</text>
</view>
<view class="info-panel__row">
<text class="info-panel__label">Compass Tune</text>
<text class="info-panel__value">{{compassTuningProfileText}}</text>
</view>
<view class="control-row">
<view class="control-chip {{compassTuningProfile === 'smooth' ? 'control-chip--active' : 'control-chip--secondary'}}" bindtap="handleSetCompassTuningSmooth">顺滑</view>
<view class="control-chip {{compassTuningProfile === 'balanced' ? 'control-chip--active' : 'control-chip--secondary'}}" bindtap="handleSetCompassTuningBalanced">平衡</view>
<view class="control-chip {{compassTuningProfile === 'responsive' ? 'control-chip--active' : 'control-chip--secondary'}}" bindtap="handleSetCompassTuningResponsive">跟手</view>
</view>
<view class="info-panel__row info-panel__row--stack">
<text class="info-panel__label">Accel</text>
<text class="info-panel__value">{{accelerometerText}}</text>
</view>
<view class="info-panel__row info-panel__row--stack">
<text class="info-panel__label">Gyro</text>
<text class="info-panel__value">{{gyroscopeText}}</text>
</view>
<view class="info-panel__row info-panel__row--stack">
<text class="info-panel__label">Motion</text>
<text class="info-panel__value">{{deviceMotionText}}</text>
</view>
<view class="info-panel__row info-panel__row--stack">
<text class="info-panel__label">North Ref</text>
<text class="info-panel__value">{{northReferenceText}}</text>
</view>
<view class="control-row">
<view class="control-chip {{gpsTracking ? 'control-chip--active' : 'control-chip--secondary'}}" bindtap="handleToggleGpsTracking">{{gpsTracking ? '停止定位' : '开启定位'}}</view>
</view>
<view class="control-row">
<view class="control-chip {{locationSourceMode === 'real' ? 'control-chip--active' : 'control-chip--secondary'}}" bindtap="handleSetRealLocationMode">真实定位</view>
<view class="control-chip {{locationSourceMode === 'mock' ? 'control-chip--active' : 'control-chip--secondary'}}" bindtap="handleSetMockLocationMode">模拟定位</view>
</view>
<view class="control-row">
<view class="control-chip control-chip--secondary" bindtap="handleCycleNorthReferenceMode">{{northReferenceButtonText}}</view>
</view>
</view>
<view class="debug-section">
<view class="debug-section__header">
<view class="debug-section__title">Telemetry</view>
<view class="debug-section__desc">HUD 派生数据与心率颜色测试</view>
</view>
<view class="info-panel__row">
<text class="info-panel__label">HR</text>
<text class="info-panel__value">{{panelHeartRateValueText}} {{panelHeartRateUnitText}}</text>
</view>
<view class="info-panel__row">
<text class="info-panel__label">HR Zone</text>
<text class="info-panel__value">{{panelHeartRateZoneNameText}} {{panelHeartRateZoneRangeText}}</text>
</view>
<view class="info-panel__row">
<text class="info-panel__label">Calories</text>
<text class="info-panel__value">{{panelCaloriesValueText}} {{panelCaloriesUnitText}}</text>
</view>
<view class="info-panel__row">
<text class="info-panel__label">Speed</text>
<text class="info-panel__value">{{panelSpeedValueText}} km/h</text>
</view>
<view class="info-panel__row">
<text class="info-panel__label">Avg Speed</text>
<text class="info-panel__value">{{panelAverageSpeedValueText}} {{panelAverageSpeedUnitText}}</text>
</view>
<view class="info-panel__row">
<text class="info-panel__label">Target Dist</text>
<text class="info-panel__value">{{panelDistanceValueText}} {{panelDistanceUnitText}}</text>
</view>
<view class="info-panel__row">
<text class="info-panel__label">Accuracy</text>
<text class="info-panel__value">{{panelAccuracyValueText}} {{panelAccuracyUnitText}}</text>
</view>
<view class="control-row control-row--triple">
<view class="control-chip control-chip--secondary" bindtap="handleDebugHeartRateBlue">蓝</view>
<view class="control-chip control-chip--secondary" bindtap="handleDebugHeartRatePurple">紫</view>
<view class="control-chip control-chip--secondary" bindtap="handleDebugHeartRateGreen">绿</view>
</view>
<view class="control-row control-row--triple">
<view class="control-chip control-chip--secondary" bindtap="handleDebugHeartRateYellow">黄</view>
<view class="control-chip control-chip--secondary" bindtap="handleDebugHeartRateOrange">橙</view>
<view class="control-chip control-chip--secondary" bindtap="handleDebugHeartRateRed">红</view>
</view>
<view class="control-row">
<view class="control-chip control-chip--secondary" bindtap="handleClearDebugHeartRate">清除</view>
</view>
</view>
<view class="debug-section">
<view class="debug-section__header">
<view class="debug-section__title">Rendering</view>
<view class="debug-section__desc">地图渲染、视角与参考图层</view>
</view>
<view class="info-panel__row">
<text class="info-panel__label">Renderer</text>
<text class="info-panel__value">{{renderMode}}</text>
</view>
<view class="info-panel__row info-panel__row--stack">
<text class="info-panel__label">Projection</text>
<text class="info-panel__value">{{projectionMode}}</text>
</view>
<view class="info-panel__row">
<text class="info-panel__label">Zoom</text>
<text class="info-panel__value">{{zoom}}</text>
</view>
<view class="info-panel__row">
<text class="info-panel__label">Rotation</text>
<text class="info-panel__value">{{rotationText}}</text>
</view>
<view class="info-panel__row">
<text class="info-panel__label">Auto Source</text>
<text class="info-panel__value">{{autoRotateSourceText}}</text>
</view>
<view class="info-panel__row">
<text class="info-panel__label">Calibration</text>
<text class="info-panel__value">{{autoRotateCalibrationText}}</text>
</view>
<view class="control-row">
<view class="control-chip {{osmReferenceEnabled ? 'control-chip--active' : 'control-chip--secondary'}}" bindtap="handleToggleOsmReference">{{osmReferenceText}}</view>
<view class="control-chip" wx:if="{{orientationMode === 'manual'}}" bindtap="handleRotateStep">旋转 +15°</view>
</view>
<view class="control-row control-row--triple">
<view class="control-chip {{orientationMode === 'manual' ? 'control-chip--active' : ''}}" bindtap="handleSetManualMode">手动</view>
<view class="control-chip {{orientationMode === 'north-up' ? 'control-chip--active' : ''}}" bindtap="handleSetNorthUpMode">北朝上</view>
<view class="control-chip {{orientationMode === 'heading-up' ? 'control-chip--active' : ''}}" bindtap="handleSetHeadingUpMode">朝向朝上</view>
</view>
<view class="control-row" wx:if="{{orientationMode === 'heading-up'}}">
<view class="control-chip" bindtap="handleAutoRotateCalibrate">按当前方向校准</view>
</view>
</view>
<view class="debug-section">
<view class="debug-section__header">
<view class="debug-section__title">Diagnostics</view>
<view class="debug-section__desc">配置、瓦片缓存与运行状态</view>
</view>
<view class="info-panel__row info-panel__row--stack">
<text class="info-panel__label">Config</text>
<text class="info-panel__value">{{configStatusText}}</text>
</view>
<view class="info-panel__row info-panel__row--stack">
<text class="info-panel__label">Status</text>
<text class="info-panel__value">{{statusText}}</text>
</view>
<view class="info-panel__row info-panel__row--stack">
<text class="info-panel__label">Tile URL</text>
<text class="info-panel__value">{{tileSource}}</text>
</view>
<view class="info-panel__row">
<text class="info-panel__label">Center Tile</text>
<text class="info-panel__value">{{centerText}}</text>
</view>
<view class="info-panel__row">
<text class="info-panel__label">Tile Size</text>
<text class="info-panel__value">{{tileSizePx}}px</text>
</view>
<view class="info-panel__row">
<text class="info-panel__label">Visible Tiles</text>
<text class="info-panel__value">{{visibleTileCount}}</text>
</view>
<view class="info-panel__row">
<text class="info-panel__label">Ready Tiles</text>
<text class="info-panel__value">{{readyTileCount}}</text>
</view>
<view class="info-panel__row">
<text class="info-panel__label">Memory Tiles</text>
<text class="info-panel__value">{{memoryTileCount}}</text>
</view>
<view class="info-panel__row">
<text class="info-panel__label">Disk Tiles</text>
<text class="info-panel__value">{{diskTileCount}}</text>
</view>
<view class="info-panel__row">
<text class="info-panel__label">Cache Hit</text>
<text class="info-panel__value">{{cacheHitRateText}}</text>
</view>
<view class="info-panel__row">
<text class="info-panel__label">Disk Hits</text>
<text class="info-panel__value">{{diskHitCount}}</text>
</view>
<view class="info-panel__row">
<text class="info-panel__label">Net Fetches</text>
<text class="info-panel__value">{{networkFetchCount}}</text>
</view>
</view>
</scroll-view>
</view>
</view>
</view>