|
|
@@ -16,6 +16,9 @@
|
|
|
leftButton="back"
|
|
|
/>
|
|
|
</FlexCol>
|
|
|
+ <FlexCol position="absolute" :bottom="630" :right="30" :zIndex="100">
|
|
|
+ <Button icon="my-location" :iconProps="{ size: 40 }" @click="goToCurrentLocation" />
|
|
|
+ </FlexCol>
|
|
|
<map
|
|
|
id="map"
|
|
|
:markers="markers"
|
|
|
@@ -36,123 +39,122 @@
|
|
|
:dragSnapHeights="[ 80, 300, 700 ]"
|
|
|
>
|
|
|
<template #content>
|
|
|
- <!-- 景点详情 -->
|
|
|
- <FlexCol v-if="currentScenicSpot" position="relative" :padding="30" :gap="20">
|
|
|
- <FlexRow :gap="20" justify="space-between">
|
|
|
- <IconButton
|
|
|
- icon="arrow-left-bold"
|
|
|
- shape="round"
|
|
|
- width="40"
|
|
|
- height="40"
|
|
|
- @click="currentScenicSpot = undefined"
|
|
|
- />
|
|
|
- <Image :src="currentScenicSpot.image" :radius="20" :width="80" :height="80" mode="aspectFill" />
|
|
|
- <FlexCol>
|
|
|
- <Text>{{ currentScenicSpot.name }}</Text>
|
|
|
- <Text>{{ currentScenicSpot.address }}</Text>
|
|
|
+ <FlexCol v-if="travalDetail" :padding="25" :gap="20">
|
|
|
+ <H2>{{ travalDetail.title }}</H2>
|
|
|
+ <Text>{{ travalDetail.desc }}</Text>
|
|
|
+ <Tabs
|
|
|
+ v-model:currentIndex="currentTabIndex"
|
|
|
+ :autoItemWidth="false"
|
|
|
+ :tabs="[
|
|
|
+ { text: '路线规划', width: 140 },
|
|
|
+ { text: '路线介绍', width: 140 },
|
|
|
+ ]"
|
|
|
+ />
|
|
|
+ <!-- 路线规划 -->
|
|
|
+ <FlexCol v-if="currentTabIndex === 0" :gap="20">
|
|
|
+ <FlexCol :gap="20">
|
|
|
+ <Text color="text.second">导航偏好</Text>
|
|
|
+ <scroll-view :scroll-x="true" :style="{ width: '100%' }">
|
|
|
+ <FlexRow :gap="10">
|
|
|
+ <Button
|
|
|
+ v-for="way in preferredWays"
|
|
|
+ :key="way"
|
|
|
+ :text="getRouteToNextBestWayText(way as RouteToNextBestWay)"
|
|
|
+ :type="way === userPreferredWay ? 'primary' : 'default'"
|
|
|
+ @click="(userPreferredWay = way as RouteToNextBestWay)"
|
|
|
+ />
|
|
|
+ </FlexRow>
|
|
|
+ </scroll-view>
|
|
|
</FlexCol>
|
|
|
- <Button
|
|
|
- text="导航"
|
|
|
- icon="map"
|
|
|
- size="large"
|
|
|
- shape="round"
|
|
|
- :radius="40"
|
|
|
- @click="openLocation(currentScenicSpot)"
|
|
|
- />
|
|
|
- </FlexRow>
|
|
|
- <scroll-view :scroll-x="true" :style="{ height: '100%' }">
|
|
|
- <FlexRow :gap="10">
|
|
|
- <Image
|
|
|
- v-for="image in currentScenicSpot.images"
|
|
|
- :key="image"
|
|
|
- :src="image"
|
|
|
- :radius="20"
|
|
|
- :width="600"
|
|
|
- :height="280"
|
|
|
- mode="aspectFill"
|
|
|
- touchable
|
|
|
- @click="previewImage(image, currentScenicSpot.images)"
|
|
|
- />
|
|
|
- </FlexRow>
|
|
|
- </scroll-view>
|
|
|
- <Parse :content="currentScenicSpot.intro" />
|
|
|
- </FlexCol>
|
|
|
- <!-- 路线规划 -->
|
|
|
- <FlexCol v-else-if="travalDetail" :padding="25" :gap="20">
|
|
|
- <FlexCol>
|
|
|
- <H2>{{ travalDetail.title }}</H2>
|
|
|
- <Text>{{ travalDetail.desc }}</Text>
|
|
|
- </FlexCol>
|
|
|
- <FlexCol :gap="20">
|
|
|
- <Text color="text.second">导航偏好</Text>
|
|
|
- <scroll-view :scroll-x="true" :style="{ width: '100%' }">
|
|
|
- <FlexRow :gap="10">
|
|
|
- <Button
|
|
|
- v-for="way in preferredWays"
|
|
|
- :key="way"
|
|
|
- :text="getRouteToNextBestWayText(way as RouteToNextBestWay)"
|
|
|
- :type="way === userPreferredWay ? 'primary' : 'default'"
|
|
|
- @click="(userPreferredWay = way as RouteToNextBestWay)"
|
|
|
- />
|
|
|
- </FlexRow>
|
|
|
- </scroll-view>
|
|
|
- </FlexCol>
|
|
|
- <FlexCol :gap="20">
|
|
|
- <Text color="text.second">路线规划</Text>
|
|
|
- <Touchable
|
|
|
- v-for="item in routeInfo?.items || []" :key="item.id"
|
|
|
- :gap="20"
|
|
|
- direction="column"
|
|
|
- @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>{{ item.scenicSpot.name }}</Text>
|
|
|
- <Text color="text.second">{{ item.scenicSpot.address }}</Text>
|
|
|
- </FlexCol>
|
|
|
- </FlexRow>
|
|
|
- <FlexRow align="center" :margin="[0,0,10,100]" :gap="12">
|
|
|
- <template v-if="item.toNextRoute && item.toNextRoute['transit']">
|
|
|
- <template v-if="userPreferredWay">
|
|
|
- <Tag :text="getRouteToNextBestWayText(userPreferredWay || 'transit')" touchable @click="focusRoute(item)" />
|
|
|
- <Text :text="formatDistance(item.toNextRoute[userPreferredWay || 'transit']?.distance)" />
|
|
|
- <Text :text="formatDuration(item.toNextRoute[userPreferredWay || 'transit']?.duration)" />
|
|
|
- </template>
|
|
|
- <template v-else>
|
|
|
- <Tag :text="'推荐 ' + getRouteToNextBestWayText(item.toNextBestWay || 'transit')" touchable @click="focusRoute(item)" />
|
|
|
- <Text :text="formatDistance(item.toNextRoute[item.toNextBestWay || 'transit']?.distance)" />
|
|
|
- <Text :text="formatDuration(item.toNextRoute[item.toNextBestWay || 'transit']?.duration)" />
|
|
|
- </template>
|
|
|
- </template>
|
|
|
- </FlexRow>
|
|
|
- <!-- 公交地铁路线规划 -->
|
|
|
+ <FlexCol :gap="20">
|
|
|
+ <Text color="text.second">路线规划</Text>
|
|
|
<FlexCol
|
|
|
- v-if="item.toNextRoute && item.toNextRoute['transit'] && (userPreferredWay === 'transit' || item.toNextBestWay === 'transit' || !item.toNextBestWay)"
|
|
|
- :gap="8"
|
|
|
- :margin="[0,0,0,100]"
|
|
|
+ v-for="(item, index) in routeInfo?.items || []" :key="item.id"
|
|
|
+ :gap="20"
|
|
|
>
|
|
|
- <FlexCol v-for="(step, stepIdx) in (item.toNextRoute.transit.steps || [])" :key="stepIdx" :gap="4">
|
|
|
- <template v-if="step.mode === 'WALKING'">
|
|
|
- <FlexRow :gap="8" align="center">
|
|
|
- <Text color="text.second">{{ stepIdx + 1 }}. 步行</Text>
|
|
|
- <Text>{{ formatDistance(step.distance) }} · 约 {{ formatDuration(step.duration) }}</Text>
|
|
|
- </FlexRow>
|
|
|
- </template>
|
|
|
- <template v-else-if="step.mode === 'TRANSIT' && step.lines?.length">
|
|
|
- <FlexCol v-for="(line, lineIdx) in step.lines" :key="lineIdx" :gap="2">
|
|
|
- <FlexRow :gap="8" align="center">
|
|
|
- <Text color="text.second">{{ stepIdx + 1 }}. {{ line.vehicle === 'BUS' ? '公交' : line.vehicle === 'SUBWAY' ? '地铁' : line.vehicle === 'RAIL' ? '火车' : '公交' }}</Text>
|
|
|
- <Text bold>{{ line.title }}</Text>
|
|
|
- </FlexRow>
|
|
|
- <Text color="text.second" :margin="[0,0,0,8]">{{ line.geton?.title }} → {{ line.getoff?.title }}</Text>
|
|
|
- <Text color="text.second">{{ formatDistance(line.distance) }} · 约 {{ formatDuration(line.duration) }} · {{ line.station_count || 0 }} 站</Text>
|
|
|
+ <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[index]">打卡点 {{ (index + 1) }}</Text><!-- //如果显示天数则用 item.atDay -->
|
|
|
+ <Text>{{ item.scenicSpot.name }}</Text>
|
|
|
+ <Text color="text.second">{{ item.scenicSpot.address }}</Text>
|
|
|
+ </FlexCol>
|
|
|
+ </FlexRow>
|
|
|
+ <FlexCol center :gap="10" :innerStyle="{ minWidth: '150rpx' }">
|
|
|
+ <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" :text="getDistance(item)" />
|
|
|
+ </template>
|
|
|
+ </FlexCol>
|
|
|
+ </Touchable>
|
|
|
+ <NextBestWay
|
|
|
+ :toNextRoute="item.toNextRoute"
|
|
|
+ :toNextBestWay="item.toNextBestWay"
|
|
|
+ :userPreferredWay="userPreferredWay"
|
|
|
+ @focusRoute="focusRoute(item)"
|
|
|
+ >
|
|
|
+ <template #extra="{ finalWay }">
|
|
|
+ <!-- 公交地铁路线规划 -->
|
|
|
+ <FlexCol
|
|
|
+ v-if="item.toNextRoute && item.toNextRoute['transit'] && finalWay === 'transit'"
|
|
|
+ :gap="8"
|
|
|
+ :margin="[10,0,10,100]"
|
|
|
+ >
|
|
|
+ <FlexCol v-for="(step, stepIdx) in (item.toNextRoute.transit.steps || [])" :key="stepIdx" :gap="4">
|
|
|
+ <template v-if="step.mode === 'WALKING'">
|
|
|
+ <FlexRow :gap="8" align="center">
|
|
|
+ <Tag type="primary" :text="(stepIdx + 1).toString()" />
|
|
|
+ <Icon icon="walk" :size="40" />
|
|
|
+ <Text color="text.second">步行</Text>
|
|
|
+ <Text>{{ formatDistance(step.distance) }} · 约 {{ formatDuration(step.duration) }}</Text>
|
|
|
+ </FlexRow>
|
|
|
+ </template>
|
|
|
+ <template v-else-if="step.mode === 'TRANSIT' && step.lines?.length">
|
|
|
+ <FlexRow :gap="8" align="center">
|
|
|
+ <Tag type="success" :text="(stepIdx + 1).toString()" />
|
|
|
+ <Icon icon="bus" :size="40" />
|
|
|
+ <Button
|
|
|
+ v-if="step.lines?.length > 1"
|
|
|
+ type="text"
|
|
|
+ rightIcon="arrow-down"
|
|
|
+ :text="step.lines?.length > 1 ? `可搭乘 ${step.lines[0].title} 等 ${step.lines?.length} 条线路` : ''"
|
|
|
+ @click="(step as any).open=true"
|
|
|
+ />
|
|
|
+ </FlexRow>
|
|
|
+ <FlexCol v-for="(line, lineIdx) in step.lines" :key="lineIdx" :gap="10" :padding="[0,0,0,50]">
|
|
|
+ <FlexRow :gap="8" align="center">
|
|
|
+ <template v-if="line.vehicle === 'BUS'">
|
|
|
+ <Icon v-if="line.vehicle === 'BUS'" icon="bus" :size="40" />
|
|
|
+ <Text color="text.second">公交</Text>
|
|
|
+ </template>
|
|
|
+ <template v-else-if="line.vehicle === 'SUBWAY'">
|
|
|
+ <Icon icon="subway" :size="40" />
|
|
|
+ <Text color="text.second">地铁</Text>
|
|
|
+ </template>
|
|
|
+ <template v-else-if="line.vehicle === 'RAIL'">
|
|
|
+ <Icon icon="rail" :size="40" />
|
|
|
+ <Text color="text.second">火车</Text>
|
|
|
+ </template>
|
|
|
+ <Text bold :color="(line as any).line_color || '#000'">{{ line.title }}</Text>
|
|
|
+ <Text color="text.second" :margin="[0,0,0,8]">{{ line.geton?.title }} → {{ line.getoff?.title }}</Text>
|
|
|
+ </FlexRow>
|
|
|
+ <Text color="text.second">约 {{ formatDuration(line.duration) }} · {{ line.station_count || 0 }} 站</Text>
|
|
|
+ </FlexCol>
|
|
|
+ </template>
|
|
|
+ </FlexCol>
|
|
|
</FlexCol>
|
|
|
</template>
|
|
|
- </FlexCol>
|
|
|
+ </NextBestWay>
|
|
|
</FlexCol>
|
|
|
- </Touchable>
|
|
|
+ </FlexCol>
|
|
|
+ <Height :height="100" />
|
|
|
+ </FlexCol>
|
|
|
+ <!-- 路线介绍 -->
|
|
|
+ <FlexCol v-if="currentTabIndex === 1">
|
|
|
+ <Parse :content="travalDetail.content" />
|
|
|
+ <Height :height="100" />
|
|
|
</FlexCol>
|
|
|
</FlexCol>
|
|
|
</template>
|
|
|
@@ -183,6 +185,12 @@ import Touchable from '@/components/feedback/Touchable.vue';
|
|
|
import Parse from '@/components/display/parse/Parse.vue';
|
|
|
import IconButton from '@/components/basic/IconButton.vue';
|
|
|
import { alert } from '@/components/utils/DialogAction';
|
|
|
+import Tabs from '@/components/nav/Tabs.vue';
|
|
|
+import Icon from '@/components/basic/Icon.vue';
|
|
|
+import CollapseBox from '@/components/display/CollapseBox.vue';
|
|
|
+import NextBestWay from './components/NextBestWay.vue';
|
|
|
+import Height from '@/components/layout/space/Height.vue';
|
|
|
+import { navTo } from '@/components/utils/PageAction';
|
|
|
|
|
|
const markers = ref<any[]>([]);
|
|
|
/** 地图折线:每条 toNextRoute 一段,points 来自 toNextRoute.xxx.polyline (number[] 为 经度,纬度 交替) */
|
|
|
@@ -196,11 +204,13 @@ const polyline = ref<Array<{
|
|
|
}>>([]);
|
|
|
const circles = ref<any[]>([]);
|
|
|
|
|
|
+const currentTabIndex = ref(0);
|
|
|
const mapCtx = uni.createMapContext('map');
|
|
|
+const myLocation = ref<[number, number]>([0, 0]);
|
|
|
const currentLocation = ref<[number, number]>([0, 0]);
|
|
|
+const currentLocationGeted = ref(false);
|
|
|
const travalDetail = ref<GetContentDetailItem>();
|
|
|
const routeInfo = ref<RouteInfo>();
|
|
|
-const currentScenicSpot = ref<RouteInfo['items'][number]['scenicSpot'] | undefined>();
|
|
|
const userPreferredWay = ref<RouteToNextBestWay|''>('');
|
|
|
const bottomSheetRef = ref<BottomSheetExpose>();
|
|
|
|
|
|
@@ -210,10 +220,65 @@ 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 公式 */
|
|
|
+function getDistanceMeters(
|
|
|
+ lon1: number, lat1: number,
|
|
|
+ lon2: number, lat2: number
|
|
|
+): number {
|
|
|
+ const R = 6371000; // 地球半径 米
|
|
|
+ const dLat = (lat2 - lat1) * Math.PI / 180;
|
|
|
+ const dLon = (lon2 - lon1) * Math.PI / 180;
|
|
|
+ const a =
|
|
|
+ Math.sin(dLat / 2) * Math.sin(dLat / 2) +
|
|
|
+ Math.cos(lat1 * Math.PI / 180) * Math.cos(lat2 * Math.PI / 180) *
|
|
|
+ Math.sin(dLon / 2) * Math.sin(dLon / 2);
|
|
|
+ const c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a));
|
|
|
+ return R * c;
|
|
|
+}
|
|
|
+
|
|
|
+function goToCurrentLocation() {
|
|
|
+ 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();
|
|
|
+ console.log(err);
|
|
|
+ alert({
|
|
|
+ title: '获取位置失败',
|
|
|
+ content: '请检查是否开启定位权限',
|
|
|
+ });
|
|
|
+ },
|
|
|
+ });
|
|
|
+}
|
|
|
+function getDistance(item: RouteInfo['items'][number]): string {
|
|
|
+ const [lng, lat] = myLocation.value;
|
|
|
+ const meters = getDistanceMeters(lng, lat, item.scenicSpot.longitude, item.scenicSpot.latitude);
|
|
|
+ if (meters < 100) return '一百米内';
|
|
|
+ if (meters < 1000) return `${Math.round(meters / 100) * 100}米`;
|
|
|
+ return `${Math.round(meters / 1000)}km`;
|
|
|
+}
|
|
|
+function openLocation(item: RouteInfo['items'][number]) {
|
|
|
+ uni.openLocation({
|
|
|
+ latitude: item.scenicSpot.latitude,
|
|
|
+ longitude: item.scenicSpot.longitude,
|
|
|
+ });
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
@@ -248,20 +313,62 @@ function collectTransitPolylines(transitData: RouteInfo['items'][0]['toNextRoute
|
|
|
}
|
|
|
return result;
|
|
|
}
|
|
|
-
|
|
|
/** 折线说明文案(用于地图 segmentTexts,不含 emoji) */
|
|
|
function getSegmentLabel(way: RouteToNextBestWay, atDay: number, duration?: number): string {
|
|
|
const wayName = { driving: '驾车', walking: '步行', bicycling: '骑行', ebicycling: '电动车', transit: '公交' }[way];
|
|
|
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<{
|
|
|
points: { longitude: number; latitude: number }[];
|
|
|
color: string;
|
|
|
width: number;
|
|
|
+ level: string;
|
|
|
segmentTexts?: { name: string; startIndex: number; endIndex: number }[];
|
|
|
textStyle?: { textColor: string; strokeColor: string; fontSize: number };
|
|
|
}> = [];
|
|
|
@@ -272,7 +379,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') {
|
|
|
@@ -282,8 +389,19 @@ 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;
|
|
|
- segments.push({ points, color, width, segmentTexts, textStyle: segmentTexts ? textStyle : 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,
|
|
|
+ width,
|
|
|
+ level: 'aboveroads',
|
|
|
+ segmentTexts,
|
|
|
+ textStyle: segmentTexts ? textStyle : undefined
|
|
|
+ });
|
|
|
}
|
|
|
} else {
|
|
|
const encoded = (routeData as { polyline?: number[]; duration?: number })?.polyline;
|
|
|
@@ -292,7 +410,14 @@ function buildPolylineFromRouteInfo(info: RouteInfo) {
|
|
|
if (points.length < 2) continue;
|
|
|
const duration = (routeData as { duration?: number })?.duration;
|
|
|
const segmentTexts = [{ name: getSegmentLabel(way, item.atDay, duration), startIndex: 0, endIndex: points.length - 1 }];
|
|
|
- segments.push({ points, color, width, segmentTexts, textStyle });
|
|
|
+ segments.push({
|
|
|
+ points,
|
|
|
+ color,
|
|
|
+ width,
|
|
|
+ level: 'aboveroads',
|
|
|
+ segmentTexts,
|
|
|
+ textStyle
|
|
|
+ });
|
|
|
}
|
|
|
}
|
|
|
polyline.value = segments;
|
|
|
@@ -301,22 +426,10 @@ function buildPolylineFromRouteInfo(info: RouteInfo) {
|
|
|
function onMarkerClick(item: any) {
|
|
|
console.log(item);
|
|
|
}
|
|
|
-function openLocation(item: RouteInfo['items'][number]['scenicSpot']) {
|
|
|
- uni.openLocation({
|
|
|
- latitude: item.latitude,
|
|
|
- longitude: item.longitude,
|
|
|
- });
|
|
|
-}
|
|
|
function onItemClick(item: RouteInfo['items'][number]) {
|
|
|
- currentScenicSpot.value = item.scenicSpot;
|
|
|
currentLocation.value = [item.scenicSpot.longitude, item.scenicSpot.latitude];
|
|
|
- bottomSheetRef.value?.setDragHeightToMax();
|
|
|
-}
|
|
|
-function previewImage(image: string, images: string[]) {
|
|
|
- uni.previewImage({
|
|
|
- urls: images,
|
|
|
- current: images.indexOf(image),
|
|
|
- });
|
|
|
+ uni.setStorageSync('travelRouteItem', item.scenicSpot);
|
|
|
+ navTo('./details');
|
|
|
}
|
|
|
function focusRoute(item: RouteInfo['items'][number]) {
|
|
|
bottomSheetRef.value?.setDragHeightToMin();
|
|
|
@@ -332,7 +445,7 @@ async function loadRoute() {
|
|
|
if (error.code == 404) {
|
|
|
alert({
|
|
|
title: '路线不存在',
|
|
|
- content: '路线未生成,请在服务器端生成路线',
|
|
|
+ content: '路线未生成,请在服务器端生成路线,ID: ' + querys.value.id,
|
|
|
});
|
|
|
return;
|
|
|
}
|
|
|
@@ -345,17 +458,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,
|
|
|
@@ -386,7 +499,12 @@ onMounted(() => {
|
|
|
uni.getLocation({
|
|
|
type: 'wgs84',
|
|
|
success: (res) => {
|
|
|
+ myLocation.value = [res.longitude, res.latitude];
|
|
|
currentLocation.value = [res.longitude, res.latitude];
|
|
|
+ currentLocationGeted.value = true;
|
|
|
+ },
|
|
|
+ fail: (err) => {
|
|
|
+ console.log(err);
|
|
|
},
|
|
|
});
|
|
|
});
|