Browse Source

📦 非遗路线优化

快乐的梦鱼 2 weeks ago
parent
commit
8553fd551f

+ 1 - 0
src/api/BaseAppServerRequestModule.ts

@@ -96,6 +96,7 @@ export class BaseAppServerRequestModule<T extends DataModel> extends RequestCore
   constructor(baseUrl: string) {
     super(UniappImplementer);
     if (!baseUrl.startsWith('http')) {
+      this.config.baseUrl = ApiCofig.baseUrl;
       BaseAppServerRequestUrlManager.pushUrlConfigListener(baseUrl, (baseUrl: string) => {
         this.config.baseUrl = baseUrl;
       });

+ 1 - 0
src/api/traval/TravalContent.ts

@@ -34,6 +34,7 @@ export class TravalContentApi extends CommonContentApi {
       'scenic_spots': '1',
     });
     res.scenicSpotsList = (res.scenicSpotsList as any[]).map(p => transformDataModel<TravalListItem>(TravalListItem, p));
+    res.keywords = (res.scenicSpotsList as any[]).map(p => p.name);
     return res;
   }
   async getTravalRouteList(params: GetContentListParams) {

+ 1 - 0
src/common/config/ApiCofig.ts

@@ -3,6 +3,7 @@
  * 说明:后端接口配置
  */
 export default {
+  baseUrl: 'https://mnwh.wenlvti.net/api',
   mapKey: 'LDXBZ-JIWWC-IXW2S-AUDZS-26VC2-GRBC4',
   mainBodyId: 1,
   platformId: 327,

+ 1 - 0
src/pages/travel/route/components/NextBestWay.vue

@@ -18,6 +18,7 @@
 
 <script setup lang="ts">
 import { formatDistance, formatDuration, getRouteToNextBestWayText, type RouteInfo, type RouteToNextBestWay } from '@/api/traval/RouteApi';
+import Text from '@/components/basic/Text.vue';
 import Tag from '@/components/display/Tag.vue';
 import FlexRow from '@/components/layout/FlexRow.vue';
 import { computed } from 'vue';

+ 78 - 15
src/pages/travel/route/travel-route.vue

@@ -69,14 +69,14 @@
             <FlexCol :gap="20">
               <Text color="text.second">路线规划</Text>
               <FlexCol 
-                v-for="item in routeInfo?.items || []" :key="item.id" 
+                v-for="(item, index) in routeInfo?.items || []" :key="item.id" 
                 :gap="20"
               >
                 <Touchable direction="row" justify="space-between" :gap="20" @click="onItemClick(item)">
                   <FlexRow :gap="20">
                     <Image :src="item.scenicSpot.image" :radius="20" :width="80" :height="80" mode="aspectFill" />
                     <FlexCol>
-                      <Text bold :color="routeColors[item.atDay]">第 {{ item.atDay }} 天</Text>
+                      <Text bold :color="routeColors[index]">打卡点 {{ (index + 1) }}</Text><!-- //如果显示天数则用 item.atDay -->
                       <Text>{{ item.scenicSpot.name }}</Text>
                       <Text color="text.second">{{ item.scenicSpot.address }}</Text>
                     </FlexCol>
@@ -85,7 +85,7 @@
                     <Button type="text" icon="navigation" text="导航" @click="openLocation(item)" />
                     <template v-if="currentLocationGeted">
                       <Text color="text.second" :fontSize="22">距您约</Text>
-                      <Text color="text.second" :fontSize="28">{{ getDistance(item) }}</Text>
+                      <Text color="text.second" :fontSize="28" :text="getDistance(item)" />
                     </template>
                   </FlexCol>
                 </Touchable>
@@ -220,10 +220,10 @@ const { querys } = useLoadQuerys({
   loadRoute();
 });
 
-const routeColors = [ '', '#22ac38', '#00a0e9', '#8957a1', '#eb6877', '#f39800', '#e60012' ];
+const routeColors = [ '#22ac38', '#00a0e9', '#8957a1', '#eb6877', '#f39800', '#e60012' ];
 const preferredWays = ['', 'driving', 'walking', 'bicycling', 'ebicycling', 'transit'];
 function getMakerImage(day: number) {
-  return `https://mncdn.wenlvti.net/app_static/minnan/images/IcoMaker${day}.png`;
+  return `https://mncdn.wenlvti.net/app_static/minnan/images/IcoMaker${(day + 1)}.png`;
 }
 
 /** 根据两点经纬度计算直线距离(米),Haversine 公式 */
@@ -243,11 +243,27 @@ function getDistanceMeters(
 }
 
 function goToCurrentLocation() {
-  if (!myLocation.value[0] || !myLocation.value[1]) return;
-  currentLocation.value = myLocation.value;
-  mapCtx.moveToLocation({
-    latitude: myLocation.value[1],
-    longitude: myLocation.value[0],
+  uni.showLoading({
+    title: '获取位置中...',
+  });
+  uni.getLocation({
+    type: 'wgs84',
+    success: (res) => {
+      uni.hideLoading();
+      myLocation.value = [res.longitude, res.latitude];
+      currentLocation.value = myLocation.value;
+      mapCtx.moveToLocation({
+        latitude: myLocation.value[1],
+        longitude: myLocation.value[0],
+      });
+    },
+    fail: (err) => {
+      uni.hideLoading();
+      alert({
+        title: '获取位置失败',
+        content: '请检查是否开启定位权限',
+      });
+    },
   });
 }
 function getDistance(item: RouteInfo['items'][number]): string {
@@ -302,6 +318,49 @@ function getSegmentLabel(way: RouteToNextBestWay, atDay: number, duration?: numb
   const dur = duration != null ? ` 约${formatDuration(duration)}` : '';
   return `第${atDay}天 ${wayName}${dur}`;
 }
+function getSegmentTransitLabel(transitData: RouteInfo['items'][0]['toNextRoute']['transit'], index: number): string {
+  if (!transitData?.steps?.length) return `公交路段${index + 1}`;
+
+  let segIndex = 0;
+  for (const step of transitData.steps) {
+    if (step.mode === 'WALKING') {
+      if (!step.polyline?.length) continue;
+      const current = segIndex++;
+      if (current !== index) continue;
+
+      const d = step.distance != null ? formatDistance(step.distance) : '';
+      const t = step.duration != null ? formatDuration(step.duration) : '';
+      if (d && t) return `步行 ${d}·约${t}`;
+      if (d) return `步行 ${d}`;
+      if (t) return `步行 约${t}`;
+      return '步行';
+    }
+
+    if (step.mode === 'TRANSIT') {
+      for (const line of (step.lines || [])) {
+        if (!line.polyline?.length) continue;
+        const current = segIndex++;
+        if (current !== index) continue;
+
+        const vehicle = (line.vehicle || '').toUpperCase();
+        const vehicleName =
+          vehicle === 'BUS' ? '公交' :
+          vehicle === 'SUBWAY' ? '地铁' :
+          vehicle === 'RAIL' ? '火车' :
+          '线路';
+
+        const title = line.title ? `${vehicleName} ${line.title}` : vehicleName;
+        const fromTo = (line.geton?.title && line.getoff?.title) ? ` ${line.geton.title}→${line.getoff.title}` : '';
+        const stations = line.station_count != null ? `·${line.station_count}站` : '';
+        const d = line.distance != null ? `·${formatDistance(line.distance)}` : '';
+        const t = line.duration != null ? `·约${formatDuration(line.duration)}` : '';
+        return `${title}${fromTo}${stations}${d}${t}`.trim();
+      }
+    }
+  }
+
+  return `公交路段${index + 1}`;
+}
 /** 根据 toNextRoute 与 toNextBestWay 生成地图 polyline 数组(含 segmentTexts 折线说明) */
 function buildPolylineFromRouteInfo(info: RouteInfo) {
   const segments: Array<{
@@ -319,7 +378,7 @@ function buildPolylineFromRouteInfo(info: RouteInfo) {
     const item = items[i];
     const way: RouteToNextBestWay = (userPreferredWay.value || item.toNextBestWay || 'driving') as RouteToNextBestWay;
     const routeData = item.toNextRoute?.[way];
-    const color = routeColors[item.atDay];
+    const color = routeColors[i]; //如果显示天数则用 item.atDay
     const width = 6;
 
     if (way === 'transit') {
@@ -329,7 +388,11 @@ function buildPolylineFromRouteInfo(info: RouteInfo) {
       for (let k = 0; k < polylines.length; k++) {
         const points = polylineToPoints(polylines[k]);
         if (points.length < 2) continue;
-        const segmentTexts = k === 0 ? [{ name: label, startIndex: 0, endIndex: points.length - 1 }] : undefined;
+        const segmentTexts = k === 0 ? [
+          { name: label, startIndex: 0, endIndex: points.length - 1 }
+        ] : [
+          { name: getSegmentTransitLabel(transitData!, k), startIndex: 0, endIndex: points.length - 1 }
+        ];
         segments.push({ 
           points, 
           color, 
@@ -394,17 +457,17 @@ async function loadMap() {
 
   // 生成标记点
   const tempMarkers = routeInfo.value.items
-    .map(p => ({
+    .map((p, index) => ({
       latitude: p.scenicSpot.latitude,
       longitude: p.scenicSpot.longitude,
-      iconPath: getMakerImage(p.atDay),
+      iconPath: getMakerImage(index),
       callout: {
         content: p.scenicSpot.name,
         color: "#ffffff",
         fontSize: 15,
         borderRadius: 15,
         padding: "10",
-        bgColor: routeColors[p.atDay],
+        bgColor: routeColors[index],
         display: "ALWAYS",
       },
       width: 40,