forked from zhouruizhe/gmTouringMiniApp
Add check-in feature and update travel planner UI
This commit is contained in:
@@ -5,9 +5,12 @@ import PoiHeroGallery from '@/components/poi/PoiHeroGallery.vue'
|
||||
import PoiTagList from '@/components/poi/PoiTagList.vue'
|
||||
import { getPoiRepository } from '@/data/poi'
|
||||
import { formatRecommendationLabel } from '@/domain/poi'
|
||||
import { getCheckInProfile } from '@/services/check-in'
|
||||
|
||||
const state = ref<'loading' | 'ready' | 'invalid' | 'error'>('loading')
|
||||
const poi = ref<PoiResolved | null>(null)
|
||||
const hasCheckedIn = ref(false)
|
||||
const checkInStorageError = ref(false)
|
||||
|
||||
function loadPoi(poiId: string) {
|
||||
state.value = 'loading'
|
||||
@@ -26,6 +29,15 @@ function loadPoi(poiId: string) {
|
||||
}
|
||||
|
||||
poi.value = result
|
||||
try {
|
||||
hasCheckedIn.value = getCheckInProfile().checkIns.some(record => record.poiId === result.id)
|
||||
checkInStorageError.value = false
|
||||
}
|
||||
catch (error) {
|
||||
console.error('Failed to load POI check-in state', error)
|
||||
hasCheckedIn.value = false
|
||||
checkInStorageError.value = true
|
||||
}
|
||||
state.value = 'ready'
|
||||
}
|
||||
catch (error) {
|
||||
@@ -34,6 +46,16 @@ function loadPoi(poiId: string) {
|
||||
}
|
||||
}
|
||||
|
||||
function openCheckIn() {
|
||||
if (!poi.value)
|
||||
return
|
||||
uni.navigateTo({ url: `/pages/check-in/index?poiId=${encodeURIComponent(poi.value.id)}` })
|
||||
}
|
||||
|
||||
function openCheckInRecords() {
|
||||
uni.navigateTo({ url: '/pages/check-in/records' })
|
||||
}
|
||||
|
||||
function returnToMap() {
|
||||
uni.navigateBack({
|
||||
fail: () => {
|
||||
@@ -65,6 +87,20 @@ onLoad((query) => {
|
||||
state.value = 'invalid'
|
||||
}
|
||||
})
|
||||
|
||||
onShow(() => {
|
||||
if (!poi.value)
|
||||
return
|
||||
try {
|
||||
hasCheckedIn.value = getCheckInProfile().checkIns.some(record => record.poiId === poi.value?.id)
|
||||
checkInStorageError.value = false
|
||||
}
|
||||
catch (error) {
|
||||
console.error('Failed to refresh POI check-in state', error)
|
||||
hasCheckedIn.value = false
|
||||
checkInStorageError.value = true
|
||||
}
|
||||
})
|
||||
</script>
|
||||
|
||||
<template>
|
||||
@@ -100,6 +136,15 @@ onLoad((query) => {
|
||||
<PoiTagList class="poi-detail-page__tags" :tags="poi.tags" />
|
||||
</view>
|
||||
|
||||
<view class="check-in-entry" :class="{ 'check-in-entry--done': hasCheckedIn }">
|
||||
<view class="check-in-entry__mark">{{ hasCheckedIn ? '✓' : '◎' }}</view>
|
||||
<view class="check-in-entry__copy">
|
||||
<text class="check-in-entry__title">{{ checkInStorageError ? '打卡数据需要处理' : hasCheckedIn ? '已留下光明足迹' : '到点打卡' }}</text>
|
||||
<text>{{ checkInStorageError ? '本机打卡数据异常,请先处理' : hasCheckedIn ? '该点位已在本机完成打卡' : '到达点位附近后,使用本次真实定位打卡' }}</text>
|
||||
</view>
|
||||
<button @click="checkInStorageError ? openCheckInRecords() : openCheckIn()">{{ checkInStorageError ? '去处理' : hasCheckedIn ? '查看' : '去打卡' }}</button>
|
||||
</view>
|
||||
|
||||
<view class="info-card">
|
||||
<view class="info-row">
|
||||
<text class="info-row__label">开放时间</text>
|
||||
@@ -197,6 +242,7 @@ style:
|
||||
}
|
||||
|
||||
.info-card,
|
||||
.check-in-entry,
|
||||
.description-section,
|
||||
.poc-notice {
|
||||
padding: 28rpx;
|
||||
@@ -206,6 +252,68 @@ style:
|
||||
border-radius: 20rpx;
|
||||
}
|
||||
|
||||
.check-in-entry {
|
||||
display: flex;
|
||||
gap: 18rpx;
|
||||
align-items: center;
|
||||
padding: 24rpx;
|
||||
}
|
||||
|
||||
.check-in-entry--done {
|
||||
background: #e8f4ee;
|
||||
border-color: #cfe4d9;
|
||||
}
|
||||
|
||||
.check-in-entry__mark {
|
||||
display: flex;
|
||||
flex: none;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
width: 62rpx;
|
||||
height: 62rpx;
|
||||
font-size: 28rpx;
|
||||
font-weight: 800;
|
||||
color: #fff;
|
||||
background: #167a5b;
|
||||
border-radius: 50%;
|
||||
}
|
||||
|
||||
.check-in-entry__copy {
|
||||
display: flex;
|
||||
flex: 1;
|
||||
flex-direction: column;
|
||||
min-width: 0;
|
||||
font-size: 21rpx;
|
||||
line-height: 32rpx;
|
||||
color: #5e6b65;
|
||||
}
|
||||
|
||||
.check-in-entry__title {
|
||||
margin-bottom: 3rpx;
|
||||
font-size: 27rpx;
|
||||
font-weight: 750;
|
||||
color: #18201d;
|
||||
}
|
||||
|
||||
.check-in-entry button {
|
||||
flex: none;
|
||||
width: auto;
|
||||
height: 60rpx;
|
||||
padding: 0 22rpx;
|
||||
margin: 0;
|
||||
font-size: 23rpx;
|
||||
font-weight: 700;
|
||||
line-height: 60rpx;
|
||||
color: #fff;
|
||||
background: #167a5b;
|
||||
border: 0;
|
||||
border-radius: 30rpx;
|
||||
}
|
||||
|
||||
.check-in-entry button::after {
|
||||
border: 0;
|
||||
}
|
||||
|
||||
.info-row {
|
||||
display: flex;
|
||||
gap: 24rpx;
|
||||
|
||||
Reference in New Issue
Block a user