lucl
2026-08-13 5544a36a97c40c44e71103bb8df4b28397de225a
Merge branch 'feature_2.6.0' into feature_v2.4.0_ui_animation
1个文件已添加
10个文件已修改
238 ■■■■■ 已修改文件
src/robotaxi/constants/music-control-feature.ts 13 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/robotaxi/pages/begin-route/components/calling-car-modules/ac-switch/index.less 2 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/robotaxi/pages/begin-route/components/calling-car-modules/ac-switch/index.tsx 18 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/robotaxi/pages/begin-route/components/calling-car-modules/music-control/index.tsx 9 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/robotaxi/pages/begin-route/components/calling-car-modules/seat-hv-control/index.tsx 19 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/robotaxi/pages/begin-route/components/calling-car-modules/temperature-control.tsx 14 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/robotaxi/pages/begin-route/components/calling-car.tsx 70 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/robotaxi/pages/begin-route/components/css-folder/calling-car.less 63 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/robotaxi/pages/begin-route/components/css-folder/fragrance-control.less 4 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/robotaxi/pages/begin-route/components/css-folder/seat-hv-control.less 23 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/robotaxi/pages/begin-route/components/css-folder/temperature-control.less 3 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/robotaxi/constants/music-control-feature.ts
New file
@@ -0,0 +1,13 @@
/**
 * 曲风(车载音乐)卡片展示开关。
 *
 * true  → 正常展示曲风卡片与控制面板,并按原逻辑发起查询/下发请求;
 * false → 曲风卡片与面板完全不展示,且不发起任何曲风相关接口请求
 *         (非接驾态、连环单等原有守卫逻辑不变)。
 *
 * 当前:暂时关闭曲风卡片。
 */
export const MUSIC_CONTROL_ENABLED = false;
/** 曲风卡片是否展示 */
export const isMusicControlEnabled = () => MUSIC_CONTROL_ENABLED;
src/robotaxi/pages/begin-route/components/calling-car-modules/ac-switch/index.less
@@ -12,6 +12,8 @@
  flex-shrink: 0;
  width: 104px;
  height: 64px;
  /* 图片右侧自带 14px 透明留白,负 margin 抵消,使开关视觉右边界与容器对齐 */
  margin-right: -14px;
}
.ac-switch-loading {
src/robotaxi/pages/begin-route/components/calling-car-modules/ac-switch/index.tsx
@@ -2,8 +2,11 @@
import './index.less';
// 图片开关三态图标(复用入口卡片同款)
const SWITCH_OPEN_ICON = 'https://s.xiaopeng.com/xp-fe/robot-taxi/imgs/v2/T-switch-open-20260709.png';
const SWITCH_CLOSE_ICON = 'https://s.xiaopeng.com/xp-fe/robot-taxi/imgs/v2/T-switch-close-20260709.png';
const SWITCH_CLOSE_ICON = 'https://s.xiaopeng.com/xp-fe/robot-taxi/imgs/v2/T-switch-close-20260812.png';
// 开启态:金色轨道 + 白色滑块(浅色背景)
const SWITCH_OPEN_ICON = 'https://s.xiaopeng.com/xp-fe/robot-taxi/imgs/v2/T-switch-open-20260812.png';
// 开启态:白色轨道 + 金色滑块(彩色/深色卡片背景)
const SWITCH_OPEN_WHITE_ICON = 'https://s.xiaopeng.com/xp-fe/robot-taxi/imgs/v2/T-switch-open-white-20260812.png';
const SWITCH_LOADING_ICON = 'https://s.xiaopeng.com/xp-fe/robot-taxi/imgs/v2/T-switch-loading-20260715.png';
type Props = {
@@ -15,16 +18,23 @@
    onChange?: () => void;
    /** 自定义 class */
    className?: string;
    /**
     * 开启态样式(关闭态两者一致):
     * - gold(默认):金色轨道 + 白色滑块,用于浅色背景(香氛卡片、弹窗内开关);
     * - white:白色轨道 + 金色滑块,用于彩色/深色卡片背景(空调入口卡片)。
     */
    theme?: 'gold' | 'white';
};
/**
 * 空调风格图片开关(开/关/loading 三态),供卡片与面板统一复用。
 */
export default function AcSwitch({ checked, loading = false, onChange, className = '' }: Props) {
export default function AcSwitch({ checked, loading = false, onChange, className = '', theme = 'gold' }: Props) {
    const openIcon = theme === 'white' ? SWITCH_OPEN_WHITE_ICON : SWITCH_OPEN_ICON;
    return (
        <Image
            className={`ac-switch${loading ? ' ac-switch-loading' : ''} ${className}`.trim()}
            src={loading ? SWITCH_LOADING_ICON : (checked ? SWITCH_OPEN_ICON : SWITCH_CLOSE_ICON)}
            src={loading ? SWITCH_LOADING_ICON : (checked ? openIcon : SWITCH_CLOSE_ICON)}
            onClick={(e: any) => { e?.stopPropagation?.(); onChange && onChange(); }}
        />
    );
src/robotaxi/pages/begin-route/components/calling-car-modules/music-control/index.tsx
@@ -4,6 +4,7 @@
import type { GenreItem } from '../../../../../api/types/genre';
import { getOrderId } from '../../../../../utils/order';
import { TripStatus } from '../../../../../constants/trip-status';
import { isMusicControlEnabled } from '../../../../../constants/music-control-feature';
import useBottomPopupAnimation from '../../hooks/use-bottom-popup-animation';
import type { ControlNodes } from '../types';
import AcSwitch from '../ac-switch';
@@ -92,13 +93,13 @@
    // 开关 loading 仅在由开关(而非磁贴)触发下发时展示
    const switchLoading = applying && applyingGenreId === '';
    // 进入接驾态查询曲风状态;连环单不查询、不展示
    // 进入接驾态查询曲风状态;功能开关关闭、连环单不查询、不展示
    useEffect(() => {
        // 门槛未就绪(如派单成功转场动效未完成):暂不查询,active 就绪后重跑再查询一次。
        if (!active) {
            return;
        }
        if (tripStatus !== TripStatus.VehicleApproaching || hasPreviousOrder) {
        if (!isMusicControlEnabled() || tripStatus !== TripStatus.VehicleApproaching || hasPreviousOrder) {
            // 离开接驾态:重置去重标记,允许下次进入接驾态时重新查询一次。
            queriedOrderIdRef.current = '';
            return;
@@ -208,8 +209,8 @@
        applyGenre(nextSwitchOn, targetGenreId, '');
    };
    // 连环单或非接驾态不展示音乐卡片
    if (tripStatus !== TripStatus.VehicleApproaching || hasPreviousOrder) {
    // 功能开关关闭、连环单或非接驾态不展示音乐卡片
    if (!isMusicControlEnabled() || tripStatus !== TripStatus.VehicleApproaching || hasPreviousOrder) {
        return { card: null, popup: null };
    }
src/robotaxi/pages/begin-route/components/calling-car-modules/seat-hv-control/index.tsx
@@ -50,6 +50,10 @@
 */
export default function SeatHvArea({ tripStatus, orderId, pageDidShowVersion = 0, hasPreviousOrder = false, active = true }: Props) {
    const [seats, setSeats] = useState<SeatHvItem[]>([]);
    // 座椅状态查询是否已出结果(成功或失败)。未出结果前整块透明,避免先闪「不可用」再切成可用
    const [queried, setQueried] = useState(false);
    // 座舱背景图是否加载完成(用于背景渐现;一旦加载过就不再重置,重开面板直接显示)
    const [bgLoaded, setBgLoaded] = useState(false);
    // 正在下发的按钮标识 `${position}:${kind}`(该按钮显示 loading,其余按钮置灰防重复),空串表示无
    const [applyingKey, setApplyingKey] = useState('');
    const querySeqRef = useRef(0);
@@ -82,11 +86,13 @@
            }
            const list: SeatHvItem[] = Array.isArray(res?.seats) ? res.seats : [];
            setSeats(list);
            setQueried(true);
        }).catch(() => {
            if (querySeqRef.current !== snapshotSeq) {
                return;
            }
            setSeats([]);
            setQueried(true);
        });
    }, [active, tripStatus, orderId, pageDidShowVersion, hasPreviousOrder]);
@@ -141,13 +147,24 @@
        }
    };
    // 查询未出结果:整块透明占位(只占据区域高度、不画任何内容),避免先闪一下「不可用」
    if (!queried) {
        return <View className='seat-hv-area'></View>;
    }
    if (!hasSeats) {
        return <View className='seat-hv-empty'>{NO_SEAT_TIP}</View>;
    }
    return (
        <View className='seat-hv-area'>
            <Image className='seat-hv-bg' src={SEAT_BG_URL} mode='widthFix' />
            <Image
                className={`seat-hv-bg${bgLoaded ? ' is-loaded' : ''}`}
                src={SEAT_BG_URL}
                mode='widthFix'
                onLoad={() => setBgLoaded(true)}
                onError={() => setBgLoaded(true)}
            />
            <View className='seat-hv-list'>
                {seats.map((seat) => {
                    const showVentilation = seat.ventilationLevels > 0;
src/robotaxi/pages/begin-route/components/calling-car-modules/temperature-control.tsx
@@ -24,7 +24,10 @@
// 入口卡片图标(复用 temperature-fragrance-control 的 v2 资源)
const AC_HEADER_ICON = 'https://s.xiaopeng.com/xp-fe/robot-taxi/imgs/v2/air-conditioner-20260716.png';
// 开启态入口卡片图标与箭头:白色版本(配合白色文字与开启态背景)
const AC_HEADER_ICON_WHITE = 'https://s.xiaopeng.com/xp-fe/robot-taxi/imgs/v2/air-conditioner-white-20260812.png';
const AC_ARROW_ICON = 'https://s.xiaopeng.com/xp-fe/robot-taxi/imgs/v2/temperature-fragrance-arrow-20260706.png';
const AC_ARROW_ICON_WHITE = 'https://s.xiaopeng.com/xp-fe/robot-taxi/imgs/v2/arrow-white-20260812.png';
const PANEL_CLOSE_ICON = 'https://s.xiaopeng.com/xp-fe/robot-taxi/imgs/close-icon.png';
const AC_TOGGLE_FAIL_TEXT = '空调开关操作失败,请重试';
const AC_TEMP_FAIL_TEXT = '温度设置失败,请重试';
@@ -32,7 +35,7 @@
const AC_TEMP_MAX_TIP_TEXT = '已到空调最高设定温度';
const TEMP_ITEM_WIDTH = 130; // 温度滑条单项宽度(所有项等宽)
const TEMP_SCROLL_SETTLE_MS = 120; // 滑动停止判定延时
const TEMP_LEFT = 10; // 滚动位移误差(适配中间放大效果)
const TEMP_LEFT = 20; // 滚动位移误差(适配中间放大效果)
type Props = {
    tripStatus: TripStatus;
@@ -477,10 +480,11 @@
            >
                <View className='tf-card-header'>
                    <View className='tf-card-header-left'>
                        <Image className='tf-card-header-icon' src={AC_HEADER_ICON} />
                        <Image className='tf-card-header-icon' src={acSwitchOn ? AC_HEADER_ICON_WHITE : AC_HEADER_ICON} />
                        <Text className='tf-card-header-title'>空调</Text>
                    </View>
                    <AcSwitch checked={acSwitchOn} loading={isTogglingAc} onChange={handleToggleAcSwitch} />
                    {/* 空调卡片为彩色背景,开启态用白色轨道 + 金色滑块 */}
                    <AcSwitch checked={acSwitchOn} loading={isTogglingAc} onChange={handleToggleAcSwitch} theme='white' />
                </View>
                <View className='tf-card-bottom'>
                    {acStatusLoaded && (
@@ -491,7 +495,7 @@
                    )}
                    <View className='tf-card-footer'>
                        <Text className='tf-card-footer-text'>调节温度|通风加热</Text>
                        <Image className='tf-card-footer-arrow' src={AC_ARROW_ICON} />
                        <Image className='tf-card-footer-arrow' src={acSwitchOn ? AC_ARROW_ICON_WHITE : AC_ARROW_ICON} />
                    </View>
                </View>
            </View>
@@ -539,7 +543,7 @@
                                                    onClick={() => handleTempItemClick(index, value)}
                                                >
                                                    <Text className='popup-temp-item-value'>{value.toFixed(1)}</Text>
                                                    {selected && <Text className='popup-temp-item-unit'>℃</Text>}
                                                    {selected && <Text className='popup-temp-item-unit'>°C</Text>}
                                                </View>
                                            );
                                        })}
src/robotaxi/pages/begin-route/components/calling-car.tsx
@@ -1,4 +1,4 @@
import { View, Image, ScrollView } from "@tarojs/components";
import { View, Image } from "@tarojs/components";
import { useState, useEffect, useRef } from 'react';
import './css-folder/calling-car.less'
import { formatRemainingDurationDisplay } from '../../../utils/format';
@@ -251,23 +251,12 @@
    }, [shouldPlayFinishedEnter]);
    /**
     * 车控(空调 / 音乐 / 香氛):卡片与弹窗分开挂载。
     * 卡片放进横向滑动的 ScrollView;弹窗是 fixed 全屏浮层,必须挂在 ScrollView 之外,
     * 否则 iOS(WKWebView)下滚动容器会成为 fixed 的包含块,弹窗被限制在卡片滑动区内。
     * 卡片放进 2 列网格容器;弹窗是 fixed 全屏浮层,单独挂在网格容器之外,避免受父容器定位影响。
     * 三个 hook 内部均按 tripStatus / hasPreviousOrder 守卫,非接驾态不发请求、返回空节点。
     */
    const acControl = useAcControl({ tripStatus, orderId, pageDidShowVersion, hasPreviousOrder, active: contentReady });
    const musicControl = useMusicControl({ tripStatus, orderId, pageDidShowVersion, hasPreviousOrder, active: contentReady });
    const fragranceControl = useFragranceControl({ tripStatus, orderId, pageDidShowVersion, hasPreviousOrder, active: contentReady });
    /**
     * 车控卡片当前横向滚动位置。
     * 弹窗开合与其弹出动画会驱动本组件重渲染,weapp 的 scroll-view 在重渲染 / 重建后会回到
     * 初始位置(最左),表现为「弹窗一出现卡片就滑回去了」。这里用 ref 记录实时位置并回传
     * scroll-left,使重渲染后停留在原处;用 ref 而非 state 是为了滚动过程中不触发额外渲染。
     */
    const cardScrollLeftRef = useRef(0);
    const handleCardScroll = (e: any) => {
        cardScrollLeftRef.current = e?.detail?.scrollLeft ?? 0;
    };
    /** 费用明细是否展开(拦截 FareDetailCard 的回调本地记录,用于切换背景与卡片布局) */
    const [detailExpanded, setDetailExpanded] = useState(false);
    /** 大号里程文案:取全程里程,单位参考 formatTripDistance(米→M,公里→KM) */
@@ -361,9 +350,22 @@
            />
            {
                // 进入接驾态即挂载蓝牙卡占位(不再以 bluetoothStatusReady 作为渲染门槛),
                // 通过 ready 控制内容淡入。蓝牙状态首轮判定是异步的(等订阅弹窗 + BLE 初始化),
                // 若等就绪后再挂载会撑高卡片产生跳变;这里先占位保留高度,就绪后仅淡入内容,高度不变。
                /* 行程操作栏:紧跟行程状态之下、蓝牙卡片之上(对齐设计稿)。
                   到达终点/已支付状态下 TripActionBar 内部按钮集合为空、自动返回 null,不占位。 */
                [TripStatus.VehicleApproaching, TripStatus.VehicleArrivedPickup, TripStatus.InService, TripStatus.TripFinished, TripStatus.PaymentSuccess].includes(tripStatus) &&
                <TripActionBar
                  tripStatus={tripStatus}
                  handleCancelTrip={handleCancelTrip}
                  showCancelTrip={showCancelTrip}
                  showShareTrip={showShareTrip}
                  handleModifyDestination={handleModifyDestination}
                  handleModifyDestinationDisabledClick={handleModifyDestinationDisabledClick}
                  showModifyDestination={showModifyDestination}
                  handleShareTrip={handleShareTrip}
                />
            }
            {
                [TripStatus.VehicleApproaching, TripStatus.VehicleArrivedPickup].includes(tripStatus) &&
                <BluetoothOperateCard
                  ready={bluetoothStatusReady}
@@ -396,23 +398,15 @@
            {
                [TripStatus.VehicleApproaching, TripStatus.VehicleArrivedPickup, TripStatus.InService].includes(tripStatus) &&
                <View className='car-card'>
                    {/* 车控卡片横向滑动(仅接驾态展示):weapp 中普通 View 的 overflow 滚动无法响应拖动,必须用 ScrollView。
                        注意:这里只放卡片,三个控制弹窗在下方 ScrollView 之外单独挂载(iOS fixed 会被滚动容器裁切) */}
                    {/* 车控卡片(仅接驾态展示):2 列网格布局,列间隔 32px,超过 2 个自动换行。
                        注意:这里只放卡片,三个控制弹窗在下方单独挂载(弹窗为 fixed 全屏浮层) */}
                    {
                        TripStatus.VehicleApproaching === tripStatus &&
                        <ScrollView
                          className='temp-fragrance-scroll'
                          scrollX
                          showScrollbar={false}
                          scrollLeft={cardScrollLeftRef.current}
                          onScroll={handleCardScroll}
                        >
                          <View className='temp-fragrance-control'>
                            {acControl.card}
                            {musicControl.card}
                            {fragranceControl.card}
                          </View>
                        </ScrollView>
                        <View className='temp-fragrance-control'>
                          {acControl.card}
                          {musicControl.card}
                          {fragranceControl.card}
                        </View>
                    }
                    <DoorTrunkControl
@@ -460,20 +454,6 @@
                      onOpenCouponSelect={onOpenCouponSelect}
                    />
                </View>
            }
            {
                /* 行程操作栏:位于费用明细卡之后、门箱控制之前(对齐设计稿) */
                [TripStatus.VehicleApproaching, TripStatus.VehicleArrivedPickup, TripStatus.InService, TripStatus.TripFinished, TripStatus.PaymentSuccess].includes(tripStatus) &&
                <TripActionBar
                  tripStatus={tripStatus}
                  handleCancelTrip={handleCancelTrip}
                  showCancelTrip={showCancelTrip}
                  showShareTrip={showShareTrip}
                  handleModifyDestination={handleModifyDestination}
                  handleModifyDestinationDisabledClick={handleModifyDestinationDisabledClick}
                  showModifyDestination={showModifyDestination}
                  handleShareTrip={handleShareTrip}
                />
            }
            <DoorTrunkControl
                tripStatus={tripStatus === TripStatus.ArrivedDestination ? TripStatus.ArrivedDestination : -1}
src/robotaxi/pages/begin-route/components/css-folder/calling-car.less
@@ -1160,45 +1160,29 @@
  }
}
/* 车控入口卡片横向滑动容器(空调 / 音乐 / 香氛,卡片固定宽度,超出宽度可横向滑动)
   用 ScrollView 而非 View + overflow:weapp WebView 渲染器会拦截 View 上的触摸手势,
   CSS overflow 滚动在真机与模拟器均无法拖动。 */
.temp-fragrance-scroll {
/* 车控入口卡片 2 列网格容器(空调 / 音乐 / 香氛):不再横向滑动,
   每行 2 个卡片、列间隔 32px,卡片宽度按内容区两等分,超过 2 个自动换行(行间隔同为 32px)。 */
.temp-fragrance-control {
  position: relative;
  z-index: 2;
  width: 100vw; /* 滑动区铺满整屏宽 */
  height: 240px; /* 与卡片等高,避免 scroll-view 高度塌陷 */
  margin-top: 8px;
  /* 左移 48px 抵消 .calling-car-content-box 的左内边距,使滑动区左边界对齐屏幕左边缘,
     卡片可一直滑到屏幕两侧边缘(首/末卡片的 48px 视觉留白由内部轨道的 padding 承担)。
     已显式指定 width: 100vw,故无需再写 margin-right(会因过约束被忽略)。 */
  margin-left: -48px;
  white-space: nowrap;
  /* 隐藏横向滚动条(show-scrollbar 仅 enhanced 模式生效,这里用 CSS 兜底) */
  &::-webkit-scrollbar,
  ::-webkit-scrollbar {
    display: none;
    width: 0;
    height: 0;
  }
}
/* 滑动轨道:宽度由卡片内容决定 */
.temp-fragrance-control {
  display: inline-flex;
  flex-wrap: nowrap;
  display: flex;
  flex-wrap: wrap;
  align-items: flex-start;
  gap: 24px;
  /* 静止时首卡对齐 48px 内容左边界;滑到底时末卡右侧同样保留 48px 留白 */
  padding-left: 48px;
  padding-right: 48px;
  gap: 32px;
  /* 卡片不参与压缩,保证各卡片保持设计稿宽度并整体溢出滚动 */
  /* 卡片外层容器:两等分内容宽度(减去一个 32px 列间隔) */
  > .ac-control,
  > .music-control,
  > .fragrance-control {
    flex-shrink: 0;
    flex: 0 0 calc((100% - 32px) / 2);
    width: calc((100% - 32px) / 2);
    min-width: 0;
  }
  /* 卡片撑满所在列(全局 .tf-card 为横滑布局下的固定 304px 宽) */
  .tf-card {
    width: 100%;
  }
}
@@ -1292,6 +1276,7 @@
  .tf-card-ac-temp-unit {
    margin-top: 8px;
    margin-left: 6px;
    font-family: @font-xpsans-bold;
    font-size: 28px;
    font-weight: 500;
    line-height: 32px;
@@ -1303,6 +1288,7 @@
    display: flex;
    align-items: center;
    justify-content: space-between;
    margin-top: 32px;
  }
  .tf-card-footer-text {
@@ -1324,14 +1310,21 @@
  padding-top: 8px;
  &.is-open {
    background-image: url('https://s.xiaopeng.com/xp-fe/robot-taxi/imgs/v2/aircondition-open-20260703.png');
    background-image: url('https://s.xiaopeng.com/xp-fe/robot-taxi/imgs/v2/aircondition-open-20260812.png');
    // 开启态卡片文字统一为白色
    .tf-card-header-title,
    .tf-card-ac-temp-value,
    .tf-card-ac-temp-unit,
    .tf-card-footer-text {
      color: #FFFFFF;
    }
  }
  &.is-close {
    background-image: url('https://s.xiaopeng.com/xp-fe/robot-taxi/imgs/v2/aircondition-close-20260703.png');
    background-image: url('https://s.xiaopeng.com/xp-fe/robot-taxi/imgs/v2/aircondition-close-20260812.png');
    // 关闭态卡片文字统一弱化
    .tf-card-header-title,
    // 关闭态卡片文字统一弱化(标题保持主题色,与香氛卡片一致)
    .tf-card-ac-temp-value,
    .tf-card-ac-temp-unit,
    .tf-card-footer-text {
src/robotaxi/pages/begin-route/components/css-folder/fragrance-control.less
@@ -28,11 +28,11 @@
  /* 香氛入口卡片:背景随开关状态切换 */
  .tf-card-fragrance {
    &.is-open {
      background-image: url('https://s.xiaopeng.com/xp-fe/robot-taxi/imgs/v2/fragrance-open-20260703.png');
      background-image: url('https://s.xiaopeng.com/xp-fe/robot-taxi/imgs/v2/fragrance-open-20260812.png');
    }
    &.is-close {
      background-image: url('https://s.xiaopeng.com/xp-fe/robot-taxi/imgs/v2/fragrance-close-20260703.png');
      background-image: url('https://s.xiaopeng.com/xp-fe/robot-taxi/imgs/v2/fragrance-close-20260812.png');
      // 关闭态卡片文字统一弱化
      .tf-card-fragrance-name,
src/robotaxi/pages/begin-route/components/css-folder/seat-hv-control.less
@@ -9,16 +9,32 @@
  }
}
// 座椅区背景图为 750×1232,容器按同比例固定高度:
// 按钮以百分比定位,容器高度提前确定后,按钮首帧即在正确位置(不再等背景图 widthFix 撑开高度)
@seat-hv-area-height: 1232px;
// 可见座椅区高度:弹窗顶部到空调白卡顶部,对应 temperature-control.less 中 .popup-ac 的 margin-top
@seat-hv-visible-height: 772px;
// 座椅通风加热区(内嵌于「温度调节」面板)
.seat-hv-area {
  position: relative;
  width: 100%;
  height: @seat-hv-area-height;
  overflow: hidden;
  // 座舱俯视图背景(widthFix,高度按图片比例自适应,撑起区域高度)
  // 座舱俯视图背景:绝对定位不参与高度计算,加载完成后渐现
  .seat-hv-bg {
    position: absolute;
    top: 0;
    left: 0;
    width: 100%;
    display: block;
    opacity: 0;
    transition: opacity 240ms ease;
    &.is-loaded {
      opacity: 1;
    }
  }
  // 座椅节点叠放层
@@ -139,13 +155,12 @@
  }
}
// 无座椅占位
// 无座椅占位(不可用态):无背景色,铺满整个可见座椅区
.seat-hv-empty {
  height: 320px;
  height: @seat-hv-visible-height;
  display: flex;
  align-items: center;
  justify-content: center;
  background-color: #E9EBF0;
  font-size: 28px;
  color: rgba(0, 0, 0, 0.4);
}
src/robotaxi/pages/begin-route/components/css-folder/temperature-control.less
@@ -128,7 +128,8 @@
      // 居中选中项:放大加粗(空调开启时高亮)
      &.active {
        width: 220px;
        // 220px(原值)+ 左右各 20px:加大选中温度与相邻温度的间距
        width: 260px;
        .popup-temp-item-value {
          font-size: 64px;
          line-height: 72px;