|
@@ -16,6 +16,9 @@
|
|
|
leftButton="back"
|
|
leftButton="back"
|
|
|
/>
|
|
/>
|
|
|
</FlexCol>
|
|
</FlexCol>
|
|
|
|
|
+ <FlexCol position="absolute" :bottom="630" :right="30" :zIndex="100">
|
|
|
|
|
+ <Button icon="my-location" :iconProps="{ size: 40 }" @click="goToCurrentLocation" />
|
|
|
|
|
+ </FlexCol>
|
|
|
<map
|
|
<map
|
|
|
id="map"
|
|
id="map"
|
|
|
:markers="markers"
|
|
:markers="markers"
|
|
@@ -36,123 +39,124 @@
|
|
|
:dragSnapHeights="[ 80, 300, 700 ]"
|
|
:dragSnapHeights="[ 80, 300, 700 ]"
|
|
|
>
|
|
>
|
|
|
<template #content>
|
|
<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>
|
|
</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
|
|
<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 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[item.atDay]">第 {{ item.atDay }} 天</Text>
|
|
|
|
|
+ <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">{{ getDistance(item) }}</Text>
|
|
|
|
|
+ </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>
|
|
|
|
|
+ <CollapseBox :open="(step as any).open || step.lines?.length == 1">
|
|
|
|
|
+ <FlexCol v-for="(line, lineIdx) in step.lines" :key="lineIdx" :gap="10">
|
|
|
|
|
+ <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>
|
|
|
|
|
+ </CollapseBox>
|
|
|
|
|
+ </template>
|
|
|
|
|
+ </FlexCol>
|
|
|
</FlexCol>
|
|
</FlexCol>
|
|
|
</template>
|
|
</template>
|
|
|
- </FlexCol>
|
|
|
|
|
|
|
+ </NextBestWay>
|
|
|
</FlexCol>
|
|
</FlexCol>
|
|
|
- </Touchable>
|
|
|
|
|
|
|
+ </FlexCol>
|
|
|
|
|
+ <Height :height="100" />
|
|
|
|
|
+ </FlexCol>
|
|
|
|
|
+ <!-- 路线介绍 -->
|
|
|
|
|
+ <FlexCol v-if="currentTabIndex === 1">
|
|
|
|
|
+ <Parse :content="travalDetail.content" />
|
|
|
|
|
+ <Height :height="100" />
|
|
|
</FlexCol>
|
|
</FlexCol>
|
|
|
</FlexCol>
|
|
</FlexCol>
|
|
|
</template>
|
|
</template>
|
|
@@ -183,6 +187,12 @@ import Touchable from '@/components/feedback/Touchable.vue';
|
|
|
import Parse from '@/components/display/parse/Parse.vue';
|
|
import Parse from '@/components/display/parse/Parse.vue';
|
|
|
import IconButton from '@/components/basic/IconButton.vue';
|
|
import IconButton from '@/components/basic/IconButton.vue';
|
|
|
import { alert } from '@/components/utils/DialogAction';
|
|
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[]>([]);
|
|
const markers = ref<any[]>([]);
|
|
|
/** 地图折线:每条 toNextRoute 一段,points 来自 toNextRoute.xxx.polyline (number[] 为 经度,纬度 交替) */
|
|
/** 地图折线:每条 toNextRoute 一段,points 来自 toNextRoute.xxx.polyline (number[] 为 经度,纬度 交替) */
|
|
@@ -196,11 +206,13 @@ const polyline = ref<Array<{
|
|
|
}>>([]);
|
|
}>>([]);
|
|
|
const circles = ref<any[]>([]);
|
|
const circles = ref<any[]>([]);
|
|
|
|
|
|
|
|
|
|
+const currentTabIndex = ref(0);
|
|
|
const mapCtx = uni.createMapContext('map');
|
|
const mapCtx = uni.createMapContext('map');
|
|
|
|
|
+const myLocation = ref<[number, number]>([0, 0]);
|
|
|
const currentLocation = ref<[number, number]>([0, 0]);
|
|
const currentLocation = ref<[number, number]>([0, 0]);
|
|
|
|
|
+const currentLocationGeted = ref(false);
|
|
|
const travalDetail = ref<GetContentDetailItem>();
|
|
const travalDetail = ref<GetContentDetailItem>();
|
|
|
const routeInfo = ref<RouteInfo>();
|
|
const routeInfo = ref<RouteInfo>();
|
|
|
-const currentScenicSpot = ref<RouteInfo['items'][number]['scenicSpot'] | undefined>();
|
|
|
|
|
const userPreferredWay = ref<RouteToNextBestWay|''>('');
|
|
const userPreferredWay = ref<RouteToNextBestWay|''>('');
|
|
|
const bottomSheetRef = ref<BottomSheetExpose>();
|
|
const bottomSheetRef = ref<BottomSheetExpose>();
|
|
|
|
|
|
|
@@ -216,6 +228,44 @@ 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}.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() {
|
|
|
|
|
+ if (!myLocation.value[0] || !myLocation.value[1]) return;
|
|
|
|
|
+ currentLocation.value = myLocation.value;
|
|
|
|
|
+ mapCtx.moveToLocation({
|
|
|
|
|
+ latitude: myLocation.value[1],
|
|
|
|
|
+ longitude: myLocation.value[0],
|
|
|
|
|
+ });
|
|
|
|
|
+}
|
|
|
|
|
+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,
|
|
|
|
|
+ });
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
/**
|
|
/**
|
|
|
* 腾讯地图 polyline 解压并转为地图组件 points
|
|
* 腾讯地图 polyline 解压并转为地图组件 points
|
|
|
* 文档:https://lbs.qq.com/service/webService/webServiceGuide/route/webServiceRoute#8
|
|
* 文档:https://lbs.qq.com/service/webService/webServiceGuide/route/webServiceRoute#8
|
|
@@ -248,20 +298,19 @@ function collectTransitPolylines(transitData: RouteInfo['items'][0]['toNextRoute
|
|
|
}
|
|
}
|
|
|
return result;
|
|
return result;
|
|
|
}
|
|
}
|
|
|
-
|
|
|
|
|
/** 折线说明文案(用于地图 segmentTexts,不含 emoji) */
|
|
/** 折线说明文案(用于地图 segmentTexts,不含 emoji) */
|
|
|
function getSegmentLabel(way: RouteToNextBestWay, atDay: number, duration?: number): string {
|
|
function getSegmentLabel(way: RouteToNextBestWay, atDay: number, duration?: number): string {
|
|
|
const wayName = { driving: '驾车', walking: '步行', bicycling: '骑行', ebicycling: '电动车', transit: '公交' }[way];
|
|
const wayName = { driving: '驾车', walking: '步行', bicycling: '骑行', ebicycling: '电动车', transit: '公交' }[way];
|
|
|
const dur = duration != null ? ` 约${formatDuration(duration)}` : '';
|
|
const dur = duration != null ? ` 约${formatDuration(duration)}` : '';
|
|
|
return `第${atDay}天 ${wayName}${dur}`;
|
|
return `第${atDay}天 ${wayName}${dur}`;
|
|
|
}
|
|
}
|
|
|
-
|
|
|
|
|
/** 根据 toNextRoute 与 toNextBestWay 生成地图 polyline 数组(含 segmentTexts 折线说明) */
|
|
/** 根据 toNextRoute 与 toNextBestWay 生成地图 polyline 数组(含 segmentTexts 折线说明) */
|
|
|
function buildPolylineFromRouteInfo(info: RouteInfo) {
|
|
function buildPolylineFromRouteInfo(info: RouteInfo) {
|
|
|
const segments: Array<{
|
|
const segments: Array<{
|
|
|
points: { longitude: number; latitude: number }[];
|
|
points: { longitude: number; latitude: number }[];
|
|
|
color: string;
|
|
color: string;
|
|
|
width: number;
|
|
width: number;
|
|
|
|
|
+ level: string;
|
|
|
segmentTexts?: { name: string; startIndex: number; endIndex: number }[];
|
|
segmentTexts?: { name: string; startIndex: number; endIndex: number }[];
|
|
|
textStyle?: { textColor: string; strokeColor: string; fontSize: number };
|
|
textStyle?: { textColor: string; strokeColor: string; fontSize: number };
|
|
|
}> = [];
|
|
}> = [];
|
|
@@ -283,7 +332,7 @@ function buildPolylineFromRouteInfo(info: RouteInfo) {
|
|
|
const points = polylineToPoints(polylines[k]);
|
|
const points = polylineToPoints(polylines[k]);
|
|
|
if (points.length < 2) continue;
|
|
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 }] : undefined;
|
|
|
- segments.push({ points, color, width, segmentTexts, textStyle: segmentTexts ? textStyle : undefined });
|
|
|
|
|
|
|
+ segments.push({ points, color, width, level: 'aboveroads', segmentTexts, textStyle: segmentTexts ? textStyle : undefined });
|
|
|
}
|
|
}
|
|
|
} else {
|
|
} else {
|
|
|
const encoded = (routeData as { polyline?: number[]; duration?: number })?.polyline;
|
|
const encoded = (routeData as { polyline?: number[]; duration?: number })?.polyline;
|
|
@@ -292,7 +341,14 @@ function buildPolylineFromRouteInfo(info: RouteInfo) {
|
|
|
if (points.length < 2) continue;
|
|
if (points.length < 2) continue;
|
|
|
const duration = (routeData as { duration?: number })?.duration;
|
|
const duration = (routeData as { duration?: number })?.duration;
|
|
|
const segmentTexts = [{ name: getSegmentLabel(way, item.atDay, duration), startIndex: 0, endIndex: points.length - 1 }];
|
|
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;
|
|
polyline.value = segments;
|
|
@@ -301,22 +357,10 @@ function buildPolylineFromRouteInfo(info: RouteInfo) {
|
|
|
function onMarkerClick(item: any) {
|
|
function onMarkerClick(item: any) {
|
|
|
console.log(item);
|
|
console.log(item);
|
|
|
}
|
|
}
|
|
|
-function openLocation(item: RouteInfo['items'][number]['scenicSpot']) {
|
|
|
|
|
- uni.openLocation({
|
|
|
|
|
- latitude: item.latitude,
|
|
|
|
|
- longitude: item.longitude,
|
|
|
|
|
- });
|
|
|
|
|
-}
|
|
|
|
|
function onItemClick(item: RouteInfo['items'][number]) {
|
|
function onItemClick(item: RouteInfo['items'][number]) {
|
|
|
- currentScenicSpot.value = item.scenicSpot;
|
|
|
|
|
currentLocation.value = [item.scenicSpot.longitude, item.scenicSpot.latitude];
|
|
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]) {
|
|
function focusRoute(item: RouteInfo['items'][number]) {
|
|
|
bottomSheetRef.value?.setDragHeightToMin();
|
|
bottomSheetRef.value?.setDragHeightToMin();
|
|
@@ -332,7 +376,7 @@ async function loadRoute() {
|
|
|
if (error.code == 404) {
|
|
if (error.code == 404) {
|
|
|
alert({
|
|
alert({
|
|
|
title: '路线不存在',
|
|
title: '路线不存在',
|
|
|
- content: '路线未生成,请在服务器端生成路线',
|
|
|
|
|
|
|
+ content: '路线未生成,请在服务器端生成路线,ID: ' + querys.value.id,
|
|
|
});
|
|
});
|
|
|
return;
|
|
return;
|
|
|
}
|
|
}
|
|
@@ -386,8 +430,11 @@ onMounted(() => {
|
|
|
uni.getLocation({
|
|
uni.getLocation({
|
|
|
type: 'wgs84',
|
|
type: 'wgs84',
|
|
|
success: (res) => {
|
|
success: (res) => {
|
|
|
|
|
+ myLocation.value = [res.longitude, res.latitude];
|
|
|
currentLocation.value = [res.longitude, res.latitude];
|
|
currentLocation.value = [res.longitude, res.latitude];
|
|
|
|
|
+ currentLocationGeted.value = true;
|
|
|
},
|
|
},
|
|
|
|
|
+
|
|
|
});
|
|
});
|
|
|
});
|
|
});
|
|
|
|
|
|