feat(travel): 接入远端 AI 推荐服务,支持 GLM real 模式与本地静默回退
AI Code Review / review (pull_request) Successful in 1s

- createPlan 在配置 VITE_TRAVEL_ASSISTANT_API_BASE_URL 时调用 FastAPI 推荐服务
  做无坐标选点,路线/交通/时长仍由本机核算;远端不可用即静默回退本地规划
- 放开 loadPlan 对远端行程的回读限制(原 AI 冻结期禁用),行程页跳转不再丢行程
- planner/assistant 文案按是否启用远端如实切换,不再谎称「本期不调用 AI」
- 新增远端接通/回退/候选载荷单测;server/README 更新联调与 real 模式说明
- .env.development 默认指向已部署推荐服务;server/.env.example 补 GLM 示例

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
周瑞哲
2026-08-04 17:22:38 +08:00
co-authored by Claude Fable 5
parent 377efbffa8
commit 0a00cd5b3a
9 changed files with 183 additions and 12 deletions
+3 -2
View File
@@ -2,7 +2,7 @@
import type { PoiResolved } from '@/domain/poi'
import TravelPoiCard from '@/components/travel/TravelPoiCard.vue'
import { getPoiRepository } from '@/data/poi'
import { loadPlan } from '@/services/travel-assistant'
import { isRemoteTravelAssistantEnabled, loadPlan } from '@/services/travel-assistant'
import { useMapStore } from '@/stores'
interface AssistantPrompt {
@@ -16,6 +16,7 @@ interface AssistantPrompt {
const mapStore = useMapStore()
const featuredPois = ref<PoiResolved[]>([])
const hasSavedPlan = ref(false)
const remoteAssistantEnabled = isRemoteTravelAssistantEnabled()
const prompts: AssistantPrompt[] = [
{
@@ -166,7 +167,7 @@ onShow(loadAssistantHome)
<view class="assistant-notice">
<text class="assistant-notice__title">POC 能力边界</text>
<text>本期不调用 AI助手使用本地 POI 和确定性规则生成路线当前路线为推荐游览顺序不提供实时路况或逐段导航</text>
<text>{{ remoteAssistantEnabled ? '已接入远端 AI:仅把无坐标的点位摘要发给模型选点,路线、交通与时长仍由本机核算;当前路线为推荐游览顺序,不提供实时路况或逐段导航。' : '本期不调用 AI助手使用本地 POI 和确定性规则生成路线当前路线为推荐游览顺序不提供实时路况或逐段导航。' }}</text>
</view>
</view>
</view>
+5 -4
View File
@@ -4,7 +4,7 @@ import type { BudgetLevel, Interest, Pace, PlanningRequest, Theme, Transport, Tr
import { getPoiRepository } from '@/data/poi'
import { TravelValidationError } from '@/domain/travel'
import { isLocationSnapshotFresh } from '@/services/location'
import { createPlan, loadPlanningRequest, loadPreferences, savePlan, savePreferences } from '@/services/travel-assistant'
import { createPlan, isRemoteTravelAssistantEnabled, loadPlanningRequest, loadPreferences, savePlan, savePreferences } from '@/services/travel-assistant'
import { useLocationStore } from '@/stores'
interface PlannerPreset {
@@ -88,7 +88,8 @@ const durationText = computed(() => {
})
const usesCurrentLocation = computed(() => locationAvailable.value
&& (planningMode.value === 'quick' || customStartsFromCurrentLocation.value))
const planningEngineLabel = '本地 POC 规划'
const remoteAssistantEnabled = isRemoteTravelAssistantEnabled()
const planningEngineLabel = remoteAssistantEnabled ? 'AI 辅助选点(远端)' : '本地 POC 规划'
const locationActionText = computed(() => {
if (locationStore.status === 'locating')
return '定位中…'
@@ -466,7 +467,7 @@ onUnload(deactivatePlannerPage)
<text class="planning-mode-card__copy">从全部 POI 中选 2-8 个编排</text>
</button>
</view>
<text class="planning-mode-tip">本期由本机完成选点顺序交通估算与时长核算</text>
<text class="planning-mode-tip">{{ remoteAssistantEnabled ? 'AI 从审核点位白名单中选点;顺序、交通估算与时长核算由本机完成。' : '本期由本机完成选点、顺序、交通估算与时长核算。' }}</text>
</view>
<view class="planning-origin" :class="{ 'planning-origin--ready': locationAvailable }">
@@ -695,7 +696,7 @@ onUnload(deactivatePlannerPage)
</view>
<text class="planner-footer">
匿名使用 · 本期不调用 AI · 路线与偏好仅保存在本机
{{ remoteAssistantEnabled ? '匿名使用 · AI 仅收到无坐标的点位摘要 · 路线与偏好仅存本机' : '匿名使用 · 本期不调用 AI · 路线与偏好仅保存在本机' }}
</text>
</view>
</template>