实用指南:vue3: baidusubway using typescript

项目结构:

                                                                                    地铁线路图例                                          {{ line.name }}                                     import { defineComponent, ref, onMounted, onUnmounted, watch} from 'vue';  //,PropType     interface SubwayLine {    id: string;    name: string;    color?: string;  }     interface RouteStep {    instruction: string;    distance?: number;    duration?: number;  }     interface RouteResult {    steps: RouteStep[];    distance?: number;    duration?: number;  }     export default defineComponent({    name: 'BaiduSubwayMap',         props: {      currentCity: {        type: String,        required: true      },      startStation: {        type: String,        required: true      },      endStation: {        type: String,        required: true      },      cityData: Object as () => Record  //vue 3.3      //Vue 3      //cityData: {        //type: Object as PropType>,        //required: true      //}    },         emits: ['routeFound', 'error', 'mapLoaded'],         setup(props, { emit }) {      const subway = ref(null);      const direction = ref(null);      const subwayLines = ref([]);      const isMapLoaded = ref(false);             // 监听城市变化        watch(() => props.currentCity, async (newCity, oldCity) => {        if (newCity !== oldCity) {            console.log(`城市切换: ${oldCity} → ${newCity}`);            await loadCitySubway(newCity);        }        });        // 生命周期钩子      onMounted(() => {        initMap();      });             onUnmounted(() => {        cleanupSubwayInstance();      });             // 监听城市或站点变化      watch([() => props.currentCity, () => props.startStation, () => props.endStation], () => {        if (isMapLoaded.value && props.startStation && props.endStation) {          searchRoute();        }      });             // 初始化地图      const initMap = () => {        try {          // 检查百度地图API是否加载成功          if (typeof BMapSub === 'undefined') {            emit('error', '百度地图API加载失败,请检查API密钥是否正确');            return;          }                     // 加载当前城市的地铁地图          loadCitySubway(props.currentCity);        } catch (error) {          console.error('初始化地图时出错:', error);          emit('error', '初始化地图时出错,请刷新页面');        }      };             // 加载指定城市的地铁地图      const loadCitySubway = (cityName: string) => {        // 重置地图容器        const container = document.getElementById('subway-container');        if (container) container.innerHTML = '';                 // 清理旧的地铁实例        cleanupSubwayInstance();                 try {          // 查找城市信息          const city = BMapSub.SubwayCitiesList.find(c => c.name === cityName);                     if (!city) {            emit('error', `未找到${cityName}的地铁数据,请尝试其他城市`);            return;          }          console.log(`加载${cityName}地铁地图,城市代码: ${city.citycode}`);          // 创建新的地铁实例          subway.value = new BMapSub.Subway('subway-container', city.citycode);                     // 绑定地铁加载完成事件          subway.value.addEventListener('subwayloaded', () => {            console.log(`${cityName}地铁地图加载完成`);            onSubwayLoaded(cityName);            emit('mapLoaded', true);          });                     // 绑定错误处理          subway.value.addEventListener('subwayloaderror', onSubwayLoadError);                   } catch (e) {          console.error('创建地铁实例时出错:', e);          emit('error', `加载${cityName}地铁数据失败,请稍后再试`);        }      };             // 地铁加载完成回调      const onSubwayLoaded = (cityName: string) => {        try {          // 初始化路线规划          direction.value = new BMapSub.Direction(subway.value);                     // 设置路线规划完成后的回调          direction.value.addEventListener('directioncomplete', handleRouteResults);                     isMapLoaded.value = true;          emit('mapLoaded', true);                     // 生成线路图例          generateLineLegend();                     // 如果有起点和终点,执行搜索          if (props.startStation && props.endStation) {            searchRoute();          }                   } catch (e) {          console.error('初始化地铁地图时出错:', e);          emit('error', `初始化${cityName}地铁地图失败,请稍后再试`);        }      };             // 地铁加载错误回调      const onSubwayLoadError = () => {        emit('error', `加载${props.currentCity}地铁数据失败,请稍后再试`);        isMapLoaded.value = false;      };             // 清理旧的地铁实例      const cleanupSubwayInstance = () => {        if (subway.value) {          try {            subway.value.removeEventListener('subwayloaded', onSubwayLoaded);            subway.value.removeEventListener('subwayloaderror', onSubwayLoadError);                         // 仅在地铁已初始化且有destroy方法时尝试销毁            if (isMapLoaded.value && typeof subway.value.destroy === 'function') {              // 移除路线规划器的事件监听器              if (direction.value) {                direction.value.removeEventListener('directioncomplete', handleRouteResults);                direction.value = null;              }                             // 尝试销毁地铁实例              subway.value.destroy();            }          } catch (e) {            console.error('销毁地铁实例时出错:', e);          } finally {            // 无论如何都重置地铁实例和状态            subway.value = null;            isMapLoaded.value = false;          }        }      };             // 生成线路图例      const generateLineLegend = () => {        try {          // 获取线路信息          if (!subway.value) return;                     const lines = subway.value.getLines();                     if (lines && lines.length > 0) {            // 只显示前10条线路以避免图例过长            const displayLines = lines.slice(0, 10);            subwayLines.value = displayLines.map(line => ({              id: line.id,              name: line.name,              color: line.color            }));          }        } catch (e) {          console.error('生成线路图例时出错:', e);        }      };             // 搜索路线      const searchRoute = () => {        if (!isMapLoaded.value || !direction.value) {          emit('error', '地图加载中,请稍候再试');          return;        }                 if (!props.startStation || !props.endStation) {          emit('error', '请输入起点站和终点站');          return;        }                 // 验证站点是否属于当前城市        const validStations = getValidStations(props.currentCity);        if (validStations && !validStations.includes(props.startStation)) {          emit('error', `起点站“${props.startStation}”不存在于${props.currentCity}地铁系统中`);          return;        }                 if (validStations && !validStations.includes(props.endStation)) {          emit('error', `终点站“${props.endStation}”不存在于${props.currentCity}地铁系统中`);          return;        }                 // 执行路线搜索        try {          direction.value.search(props.startStation, props.endStation);        } catch (e) {          console.error('搜索路线时出错:', e);          emit('error', '搜索路线时出错,请重试');        }      };             // 处理路线规划结果      const handleRouteResults = (results: any) => {        try {          if (!results || results.length === 0) {            emit('error', `未找到从${props.startStation}到${props.endStation}的路线,请尝试其他站点`);            return;          }                     // 选择第一条路线(通常是最优路线)          const route = results[0];                     // 格式化路线结果          const formattedRoute: RouteResult = {            steps: route.steps || [],            distance: route.distance,            duration: route.duration          };                     // 发送路线结果给父组件          emit('routeFound', formattedRoute);                   } catch (e) {          console.error('处理路线结果时出错:', e);          emit('error', '处理路线信息时出错,请重试');        }      };             // 地图缩放控制      const zoomIn = () => {        if (subway.value) {          try {            subway.value.setZoom(subway.value.getZoom() + 1);          } catch (e) {            console.error('地图缩放时出错:', e);          }        }      };             const zoomOut = () => {        if (subway.value) {          try {            subway.value.setZoom(subway.value.getZoom() - 1);          } catch (e) {            console.error('地图缩放时出错:', e);          }        }      };             // 获取当前城市的有效站点列表      const getValidStations = (cityName: string): string[] | null => {        try {          if (!subway.value) {            return null;          }                     // 获取所有线路          const lines = subway.value.getLines();                     if (!lines || lines.length === 0) {            return null;          }                     // 收集所有站点          const stations = new Set();                     lines.forEach(line => {            if (line.stations && line.stations.length > 0) {              line.stations.forEach(station => {                stations.add(station.name);              });            }          });                     return Array.from(stations);        } catch (e) {          console.error('获取站点列表时出错:', e);          return null;        }      };             return {        subwayLines,        zoomIn,        zoomOut      };    }  });         @layer utilities {    .subway-line {      display: inline-block;      width: 12px;      height: 2px;      margin: 0 4px;      vertical-align: middle;    }  }
                                  {{ panelTitle }}                                                             城市                                         0"                class="absolute left-0 right-0 top-full mt-1 bg-white rounded-lg shadow-lg z-50"              >                                  {{ suggestion }}                                                                                                                                                                                                                                   默认                                                                                                                              默认                                                                                                             {{ loadingMessage }}                                       {{ errorMessage }}                                                                                      {{ startStation }} → {{ endStation }}                                       约{{ routeResults.duration || '未知' }}分钟                                                                                                      请输入起点和终点,点击查询路线                                                                                   import { defineComponent, ref, computed, onMounted, watch } from 'vue';  import BaiduSubwayMap from '../components/BaiduSubwayMap.vue';     interface CityData {    [city: string]: {      start: string;      end: string;    };  }     export default defineComponent({    name: 'SubWayView',         components: {      BaiduSubwayMap    },         setup() {      // 状态管理      const currentCity = ref('深圳');      const startStation = ref('');      const endStation = ref('');      const panelVisible = ref(true);      const loading = ref(false);      const loadingMessage = ref('');      const errorMessage = ref('');      const routeResults = ref(null);      const cityData = ref({});      const citySuggestions = ref([]);      const cityHistory = ref([]); // 新增:历史记录数组      const panelTitle = ref('深圳地铁线路规划');  //             // 计算属性      const isDefaultStartStation = computed(() => {        return cityData.value[currentCity.value]?.start === startStation.value;      });             const isDefaultEndStation = computed(() => {        return cityData.value[currentCity.value]?.end === endStation.value;      });             // 生命周期钩子      onMounted(() => {        loadCityData();        loadSavedState();      });             // 从city.json加载城市数据      const loadCityData = async () => {        try {          console.log('开始加载城市数据...');          loading.value = true;          loadingMessage.value = '正在加载城市数据...';                     const response = await fetch('city.json');          cityData.value = await response.json();          console.log('城市数据加载成功:', cityData.value);          // 设置当前城市的默认站点          setDefaultStations();                     loading.value = false;        } catch (error) {          console.error('加载城市数据失败:', error);          errorMessage.value = '加载城市数据失败,请稍后再试';          loading.value = false;        }      };             // 加载保存的状态      const loadSavedState = () => {        try {          const savedState = localStorage.getItem('subwayMapState');                     if (savedState) {            const parsedState = JSON.parse(savedState);                         // 恢复当前城市            if (parsedState.currentCity && cityData.value[parsedState.currentCity]) {              currentCity.value = parsedState.currentCity;              panelTitle.value = `${currentCity.value}地铁线路规划`;            }                         // 恢复站点            if (parsedState.startStation) {              startStation.value = parsedState.startStation;            }                         if (parsedState.endStation) {              endStation.value = parsedState.endStation;            }                         // 恢复面板可见性            if (typeof parsedState.panelVisible === 'boolean') {              panelVisible.value = parsedState.panelVisible;            }                         console.log('从本地存储恢复状态:', parsedState);          }        } catch (e) {          console.error('恢复应用状态失败:', e);        }      };             // 保存当前状态到本地存储      const saveState = () => {        try {          const stateToSave = {            currentCity: currentCity.value,            startStation: startStation.value,            endStation: endStation.value,            panelVisible: panelVisible.value          };                     localStorage.setItem('subwayMapState', JSON.stringify(stateToSave));        } catch (e) {          console.error('保存应用状态失败:', e);        }      };             // 设置当前城市的默认站点      const setDefaultStations = () => {        const defaultStations = cityData.value[currentCity.value];                 if (defaultStations) {          // 只有在站点为空时设置默认值,保留用户修改          if (!startStation.value) {            startStation.value = defaultStations.start;          }                     if (!endStation.value) {            endStation.value = defaultStations.end;          }        }         };             // 切换城市      const changeCity = () => {        console.log(`点击:选择城市...`);         const cityName1 = currentCity.value.trim();        console.log(`点击:选择城市${cityName1}`);             const defaultStations = cityData.value[currentCity.value];                  if (defaultStations) {           startStation.value = defaultStations.start;           endStation.value = defaultStations.end;           panelTitle.value = `${currentCity.value}地铁线路规划`;           // 保存状态           saveState();         }                // 清除错误消息        errorMessage.value = null;      };             // 处理城市输入      const handleCityInput = () => {        const query = currentCity.value.trim().toLowerCase();                 if (query.length              city.toLowerCase().includes(query)        );         // 过滤匹配的城市        //const matchedCities = Object.keys(cityData.value).filter(city =>          //city.toLowerCase().includes(query)        //);                 // 更新建议列表        citySuggestions.value = matchedCities;      };             // 选择城市      const selectCity = (cityName: string) => {        currentCity.value = cityName;        console.log(`换了地图:选择城市${cityName}`);              //setDefaultStations(); // 强制设置默认站点            // itySuggestions.value = [];            if (!cityHistory.value.includes(cityName)) {                cityHistory.value.push(cityName);            }          //citySuggestions.value = [];        const defaultStations = cityData.value[currentCity.value];                  if (defaultStations) {           startStation.value = defaultStations.start;           endStation.value = defaultStations.end;           panelTitle.value = `${currentCity.value}地铁线路规划`;           // 保存状态           saveState();         }         };             // 搜索路线      const searchRoute = () => {        if (!startStation.value || !endStation.value) {          errorMessage.value = '请输入起点站和终点站';          return;        }                 // 保存当前状态        saveState();                 // 清空错误消息        //errorMessage.value = null;      };             // 处理路线结果      const handleRouteFound = (results: any) => {        routeResults.value = results;        loading.value = false;                 // 保存当前状态        saveState();      };             // 处理错误      const handleError = (message: string) => {        errorMessage.value = message;        loading.value = false;      };             // 处理地图加载完成      const handleMapLoaded = () => {        loading.value = false;      };             // 关闭面板      const closePanel = () => {        panelVisible.value = false;        saveState();      };             // 显示面板      const showPanel = () => {        panelVisible.value = true;        saveState();      };             // 重置为默认值      const resetToDefault = () => {        const defaultStations = cityData.value[currentCity.value];                 if (defaultStations) {          startStation.value = defaultStations.start;          endStation.value = defaultStations.end;          panelTitle.value = `${currentCity.value}地铁线路规划`;          // 保存状态          saveState();        }      };             // 监听面板可见性变化      watch(panelVisible, () => {        saveState();      });             // 监听站点变化      watch([startStation, endStation], () => {        saveState();      });             return {        currentCity,        startStation,        endStation,        panelVisible,        loading,        loadingMessage,        errorMessage,        routeResults,        cityData,        citySuggestions,        panelTitle,        isDefaultStartStation,        isDefaultEndStation,        changeCity,        handleCityInput,        selectCity,        searchRoute,        closePanel,        showPanel,        resetToDefault,        handleRouteFound, // 确保将方法添加到返回对象中        handleError,        handleMapLoaded      };    }  });          /* 优化字体和间距 */  @tailwind base;  @tailwind components;  @tailwind utilities;     /* 修复搜索面板层级问题 */  .z-50 {    z-index: 50;  }

输出:

posted @ 2025-07-22 16:43  yjbjingcha  阅读(18)  评论(0)    收藏  举报