findme-miniprogram-frontend/pages/map/map.wxml
2025-12-27 17:16:03 +08:00

875 lines
No EOL
40 KiB
Text
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<!--地图页面 - 高德地图集成版本-->
<view class="map-container map-with-tabbar">
<!-- 自定义导航栏 - 黑色背景70%透明度 -->
<view class="custom-navigation-bar" style="height: {{navBarHeight}}px; background-color: rgba(0, 0, 0, 0.5);">
<!-- 状态栏占位 -->
<view class="status-bar-space" style="height: {{statusBarHeight}}px;"></view>
<!-- 导航栏内容 -->
<view class="nav-content" style="height: {{navBarHeight - statusBarHeight}}px;">
<!-- 左侧占位,保持标题居中 -->
<view class="nav-left" style="width: {{menuButtonWidth}}px;"></view>
<!-- 中间标题 -->
<view class="nav-title">FindMe</view>
<!-- 右侧占位,与左侧宽度相同,确保标题居中 -->
<view class="nav-right" style="width: {{menuButtonWidth}}px;"></view>
</view>
</view>
</view>
<canvas type="2d" id="cropCanvas" style="width: 86px; height: 77px; display: none;"></canvas>
<!-- 地图组件 - 腾讯地图实现 -->
<map wx:if="{{latitude && longitude && amapReady}}" id="main-map" class="map" type="{{currentMapType}}"
show-terrain="true" show-traffic="{{showTraffic}}" latitude="{{latitude}}" longitude="{{longitude}}"
scale="{{currentMapScale}}" class="map-dark" max-scale="{{maxScale}}" markers="{{markers}}"
show-location="{{showUserLocationIndicator}}" cluster="{{true}}" clusterStyle="customClusterStyle"
show-scale="{{false}}" show-compass="false" enable-zoom="true" enable-scroll="true" enable-rotate="true"
enable-3D="true" polygons="{{polygons}}" type="{{currentMapType}}" map-style="{{mapStyle}}" enable-overlooking="true"
enable-traffic="false" enable-satellite="{{enableSatellite}}" enable-cluster="true" cluster-max-zoom="16"
cluster-grid-size="40" bindmarkertap="{{isLoggedIn ? 'onMarkerTap' : 'navigateToLogin'}}"
bindcallouttap="{{isLoggedIn ? 'onMarkerTap' : 'navigateToLogin'}}" bindregionchange="onMapRegionChange"
lines="{{busLines}}" bindlongtap="{{isLoggedIn ? 'onMapLongTap' : 'navigateToLogin'}}" bindtap="onMapTap"
bindpoitap="{{isLoggedIn ? 'onPoiTap' : 'navigateToLogin'}}" circles="{{circles}}"
style="width: 100%; height: 100%; position: absolute; top: 0; left: 0; z-index: 10;">
<cover-view slot="callout">
<block wx:for="{{markers}}" wx:key="id">
<cover-view class="customCallout" marker-id="{{item.id}}">
<!-- 用户标注(好友) -->
<block wx:if="{{item.type == 'friend-single'}}">
<cover-image class="callout-avatar" mode="aspectFill" src="{{item.avatarUrl}}"></cover-image>
<block wx:if="{{item.isOnline == true}}">
<cover-image class="callout-avatar-dot-stranger" src="/images/map/online_dot.png"></cover-image>
</block>
</block>
<block wx:elif="{{item.type == 'stranger-single'}}">
<cover-image class="callout-avatar" mode="aspectFill" src="{{item.avatarUrl}}"></cover-image>
<block wx:if="{{item.isOnline == true}}">
<cover-image class="callout-avatar-dot-stranger" src="/images/map/online_dot.png"></cover-image>
</block>
</block>
<block wx:elif="{{item.type == 'mine'}}">
<cover-view class="mine-avatar-container">
<cover-image class="callout-avatar-mine" mode="aspectFill" src="{{item.avatarUrl}}"></cover-image>
<cover-image class="callout-avatar-dot-mine" src="/images/map/online_dot.png"></cover-image>
<cover-image class="direction-indicator" wx:if="{{item.directionPath}}" src="{{item.directionPath}}"
style="transform: rotate({{item.directonAngle}}deg);">
</cover-image>
</cover-view>
</block>
<block wx:elif="{{item.type == 'search'}}">
<cover-image class="callout-avatar" src="{{item.avatarUrl}}"></cover-image>
</block>
<!-- 商家标注 - 名称高亮显示 -->
<block wx:elif="{{item.type == 'merchant'}}">
<cover-view class="callout-merchant-name {{item.isActive ? 'callout-merchant-name-active' : ''}}">{{item.merchantName || item.name}}</cover-view>
</block>
<!-- 动态标注 -->
<block wx:elif="{{item.type == 'dynamic'}}">
<cover-view class="callout-dynamic-content">{{item.content.substr(0, 20)}}{{item.content.length > 20 ? '...' :
''}}</cover-view>
</block>
<!-- 地图动态 - 单点 -->
<block wx:elif="{{item.type == 'map-feed-single'}}">
<cover-view class="callout-feed callout-feed-single">
<cover-image wx:if="{{item.avatarUrl}}" src='{{item.avatarUrl}}' class="callout-feed-thumb" mode="aspectFill" data-index="{{index}}">
</cover-image>
<cover-image wx:else class="callout-feed-thumb" mode="aspectFill" data-index="{{index}}"></cover-image>
<cover-view class="callout-actions-fixed" >
<cover-view class="action-item like-item" catchtap="toggleLike" data-index="{{index}}">
<cover-image
class="action-icon"
src="{{item.likeCount>0 ? '/images/heart-red.png' : '/images/heart-white.png'}}"
mode="widthFix"
></cover-image>
<cover-view class="action-count"> {{item.likeCount !== undefined ? (item.likeCount > 0 ? item.likeCount : 0) : 0}}</cover-view>
</cover-view>
<cover-view class="action-item comment-item">
<cover-image
class="action-icon"
src="/images/comment.png"
mode="widthFix"
></cover-image>
<cover-view class="action-count"> {{item.commentCount !== undefined ? (item.commentCount > 0 ? item.commentCount : 0) : 0}}</cover-view>
</cover-view>
</cover-view>
</cover-view>
<cover-image class="callout-arrow" src="/images/map/down_black.png" mode="widthFix"></cover-image>
</block>
<!-- 地图动态 - 聚合 -->
<block
wx:elif="{{item.type == 'map-feed-cluster' || item.type == 'friend-cluster' || item.type == 'stranger-cluster'}}">
<cover-view class="callout-feed-cluster" style="background-color: {{item.badgeColor || '#FF6F3C'}};">
<cover-view class="callout-feed-count" style="color: {{item.badgeTextColor || '#FFFFFF'}};">{{item.feedCount}}
</cover-view>
</cover-view>
</block>
<!-- 静态数据标注 -->
<block wx:elif="{{item.type == 'staticData'}}">
<cover-image class="callout-static-data-icon" src="{{item.imageUrl}}" mode="aspectFill"></cover-image>
</block>
</cover-view>
</block>
</cover-view>
<!-- 自定义比例尺(固定在右下角,示例位置) -->
<view class="custom-scale" style="bottom: 280rpx; left: 30rpx;">
<!-- 米/千米显示 -->
<view class="scale-unit metric">{{metric}}</view>
<!-- 比例尺线段(长度动态变化) -->
<view class="scale-bar">
<view class="scale-line" style="width: {{barLength}}px;"></view>
</view>
<view>
<view>
<view class="progress-fill"></view>
<!-- 英尺显示 -->
<view class="scale-unit imperial">{{imperial}}</view>
</view>
</view>
</view>
</map>
<!-- 定位中占位图 -->
<view wx:elif="{{!amapReady || (!latitude && !longitude)}}" class="location-placeholder">
<view class="placeholder-content">
<view class="location-icon">
<image src="/images/map/maker_position.png" />
</view>
<text class="placeholder-title">正在获取您的位置</text>
<text class="placeholder-subtitle">首次定位可能需要几秒钟...</text>
<view class="location-progress">
<view class="progress-bar">
<view class="progress-fill"></view>
</view>
<text class="progress-text">{{loadingText}}</text>
</view>
</view>
</view>
<!-- 顶部元素容器 - 使用flex布局来实现动态宽度 -->
<view class="top-elements-container" wx:if="{{latitude && longitude && amapReady}}"
style="top: {{navBarHeight + 12}}px; left: 0; right: 0; position: absolute; z-index: 100;">
<view class="top-elements-content">
<!-- 左侧信息区域 -->
<view class="top-left-info-container logged-in" wx:if="{{isLoggedIn}}">
<!-- 1. 地点位置 -->
<view class="location-section">
<text class="district-text {{isDarkMode ? 'dark' : ''}}" wx:if="{{currentDistrict}}">{{currentDistrict}}</text>
</view>
<!-- 2. 天气信息 -->
<view class="weather-section" wx:if="{{weatherInfo}}">
<text class="weather-icon">{{weatherInfo.icon }}</text>
<text class="weather-temp {{isDarkMode ? 'dark' : ''}}">{{weatherInfo.temperature}}°</text>
</view>
<!-- 偶遇开关按钮 -->
<!-- <view class="toggle-section">
<switch bindchange="onDynamicToggle" checked="{{isOnline}}" color="#000000" />
</view> -->
<view class="toggle-section" bindtap="onDynamicToggle">
<text class="toggle-text {{isDarkMode ? 'dark' : ''}}">{{isOnline ? '偶遇' : '偶遇'}}</text>
<!-- 直接显示当前状态的图片 -->
<image src="{{isOnline ? '/images/map/ouyu-open.png' : '/images/ouyu-close.png'}}" mode="widthFix"
class="switch-img" />
</view>
<view class="toggle-section-dynamic" bindtap="toggleMapFeedView">
<text class="toggle-text {{isDarkMode ? 'dark' : ''}}">{{mapFeedVisible ? '动态' : '动态'}}</text>
<!-- 直接显示当前状态的图片 -->
<image src="{{mapFeedVisible ? '/images/map/ouyu-open.png' : '/images/ouyu-close.png'}}" mode="widthFix"
class="switch-img" />
</view>
</view>
<!-- 中间搜索区域包含搜索按钮和搜索框根据showSearchBox状态切换显示 -->
<view class="search-area">
<!-- 搜索按钮:初始显示的搜索按钮,点击后切换为搜索框 -->
<view wx:if="{{!showSearchBox && isLoggedIn}}" class="search-btn" bindtap="showSearchBox">
<!-- 搜索图标使用SVG图标白色样式 -->
<image src="/images/map/Search-d.png" mode="aspectFit" class="search-icon" />
</view>
<view wx:elif="{{!showSearchBox && !isLoggedIn}}" class="search-btn" bindtap="navigateToLogin">
<!-- 搜索图标使用SVG图标白色样式 -->
<image src="/images/map/Search-d.png" mode="aspectFit" class="search-icon" />
</view>
<!-- 搜索框:点击搜索按钮后显示,包含输入框和关闭按钮 -->
<view wx:elif="{{showSearchBox}}" class="search-input-wrapper">
<!-- 搜索输入框:支持输入搜索关键词,绑定输入事件和确认事件 -->
<input type="text" placeholder="请输入地点名称" class="search-input" value="{{searchKeyword}}" bindinput="onSearchInput"
bindconfirm="onSearchConfirm" />
<!-- 关闭按钮:点击隐藏搜索框 -->
<view class="search-input-close" bindtap="hideSearchBox">✕</view>
</view>
</view>
<!-- 搜索结果列表 -->
<view wx:if="{{showSearchBox && searchResults.length > 0}}" class="search-results-container"
style="top: {{navBarHeight + 60}}px; left: 0; right: 0; position: absolute; z-index: 99;">
<scroll-view scroll-y="true" class="search-results-list">
<block wx:for="{{searchResults}}" wx:key="id">
<view class="search-result-item" bindtap="onSearchResultTap" data-item="{{item}}">
<view class="result-icon">{{item.icon || '📍'}}</view>
<view class="result-content">
<view class="result-name">{{item.name}}</view>
<view class="result-address">{{item.address}}</view>
</view>
</view>
</block>
</scroll-view>
</view>
<!-- 右侧按钮区域 -->
<view class="right-elements-container">
<!-- 右侧垂直按钮组 -->
<view class="right-vertical-buttons">
<!-- 个人主页按钮 -->
<view wx:if="{{isLoggedIn}}" class="user-avatar" bindtap="openProfile">
<view class="avatar-container">
<image wx:if="{{userInfo.user.avatar}}" src="{{userInfo.user.avatar}}" mode="aspectFill"
class="avatar-image" />
<image wx:else src="/images/default-stranger.png" mode="aspectFill" class="avatar-image" />
</view>
</view>
<!-- 更多按钮 -->
<view wx:if="{{isLoggedIn}}" class="more-btn" bindtap="toggleMoreMenu">
<image src="{{isDarkMode ? '/images/map/more-white.png' : '/images/map/more-black.png'}}" mode="aspectFit"
class="more-icon" />
<!-- 未读消息小红点 -->
<view class="notification-dot" wx:if="{{unreadMessageCount > 0}}"></view>
</view>
<!-- 未登录时的提示按钮 -->
<view wx:elif="{{!isLoggedIn}}" class="login-prompt-btn" bindtap="navigateToLogin">
<text class="login-prompt-text">登录</text>
</view>
</view>
</view>
</view>
</view>
<!-- 更多菜单弹窗 -->
<view class="more-menu-modal" wx:if="{{showMoreMenu}}">
<view class="more-menu-mask" bindtap="hideMoreMenu"></view>
<view class="more-menu-content">
<view class="more-menu-item" bindtap="handleAddFriend">
<image src="/images/map/AddFriend.svg" mode="aspectFit" class="more-menu-icon" />
<text class="more-menu-text">添加好友</text>
<!-- 好友请求小红点 -->
<view class="notification-dot" wx:if="{{friendRequestCount > 0}}"></view>
</view>
<view class="more-menu-item" bindtap="handleStartGroupChat">
<image src="/images/map/StartGroupChat.svg" mode="aspectFit" class="more-menu-icon" />
<text class="more-menu-text">发起群聊</text>
</view>
<view class="more-menu-item" bindtap="handleShowQRCode">
<image src="/images/map/QRCode.svg" mode="aspectFit" class="more-menu-icon" />
<text class="more-menu-text">我的二维码</text>
</view>
<view class="more-menu-item" bindtap="handleScanQRCode">
<image src="/images/map/Scan.svg" mode="aspectFit" class="more-menu-icon" />
<text class="more-menu-text">扫一扫</text>
</view>
</view>
</view>
<!-- 显示模式筛选弹窗 -->
<view class="filter-modal" wx:if="{{showFilterModal}}">
<view class="filter-mask" bindtap="hideFilterOptions"></view>
<view class="filter-options">
<view class="filter-option {{currentFilter === 'friends' ? 'active' : ''}}" bindtap="showFriendsLocation">
<text class="filter-icon">👥</text>
<text class="filter-text">仅好友</text>
</view>
<view class="filter-option {{currentFilter === 'strangers' ? 'active' : ''}}" bindtap="showNearbyPeople">
<text class="filter-icon">👤</text>
<text class="filter-text">仅陌生人</text>
</view>
<view class="filter-option {{currentFilter === 'all' ? 'active' : ''}}" bindtap="showAllLocations">
<text class="filter-icon">👨‍👩‍👧‍👦</text>
<text class="filter-text">全部用户</text>
</view>
</view>
</view>
<!-- 底部中间定位按钮 - 回到当前位置 -->
<view class="location-btn" wx:if="{{latitude && longitude && amapReady}}" style="bottom: {{safeAreaBottom + 280}}rpx;"
bindtap="centerToUserLocation">
<view class="location-btn-inner">
<view class="location-icon">
<image src="/images/map/maker_position.svg" />
</view>
<view class="location-ripple"></view>
</view>
</view>
<!-- 地图动态气泡 -->
<view wx:if="{{activeFeedBubble}}" class="feed-bubble-overlay" style="bottom: {{safeAreaBottom + 220}}rpx;">
<view class="feed-bubble-card {{activeFeedBubble.tone || 'sunset'}}">
<view class="feed-bubble-handle"></view>
<view class="feed-bubble-header">
<view class="feed-bubble-title-block">
<text class="feed-bubble-title">{{activeFeedBubble.title}}</text>
<text wx:if="{{activeFeedBubble.subtitle}}" class="feed-bubble-subtitle">{{activeFeedBubble.subtitle}}</text>
</view>
<view class="feed-bubble-chip-group">
<view wx:if="{{activeFeedBubble.chip}}" class="feed-bubble-chip">{{activeFeedBubble.chip}}</view>
<view wx:if="{{activeFeedBubble.heat}}" class="feed-bubble-chip heat">{{activeFeedBubble.heat}}</view>
</view>
<view class="feed-bubble-close" bindtap="hideFeedBubble">✕</view>
</view>
<view class="feed-bubble-meta">
<view class="feed-bubble-meta-item">
<text class="feed-bubble-meta-label">精选动态</text>
<text class="feed-bubble-meta-value">{{activeFeedBubble.feeds}}条推荐</text>
</view>
<!-- <view class="feed-bubble-meta-item" wx:if="{{activeFeedBubble.feeds}}">
<text class="feed-bubble-meta-label">精选动态</text>
<text class="feed-bubble-meta-value">{{activeFeedBubble.feeds}} 条推荐</text>
</view> -->
</view>
<view wx:if="{{activeFeedBubbleLoading}}" class="feed-bubble-loading">加载中...</view>
<view wx:else class="feed-bubble-empty">暂时没有推荐,稍后再来看看</view>
<view class="feed-bubble-actions">
<view class="feed-bubble-action primary" bindtap="onFeedBubbleMoreTap"
data-lat="{{activeFeedBubble.location.latitude}}" data-lng="{{activeFeedBubble.location.longitude}}"
data-radius="{{activeFeedBubble.radius}}">
打开附近动态
</view>
</view>
<view class="feed-bubble-tip">轻触地图空白处即可收起</view>
</view>
</view>
<view wx:if="{{activeFeedSingleVisible}}" class="feed-bubble-overlay" style="bottom: {{safeAreaBottom + 220}}rpx;">
<view class="feed-bubble-card {{activeFeedBubble.tone || 'sunset'}}">
<view class="feed-bubble-handle"></view>
<view class="feed-bubble-header">
<view class="feed-bubble-avatar">
<image src="{{activeFeedBubbleSingle.avatar || '/images/default-stranger.png'}}" mode="aspectFill"></image>
</view>
<view class="feed-bubble-user-content">
<text class="feed-bubble-user-name">{{activeFeedBubbleSingle.nickname || '匿名用户'}}</text>
<text class="feed-bubble-post-content">{{activeFeedBubbleSingle.createdAt || '发布时间'}}</text>
</view>
<view class="feed-bubble-close" bindtap="hideFeedBubble">✕</view>
</view>
<view class="feed-bubble-content">
<view class="content-inner">
{{activeFeedBubbleSingle.content}}
</view>
</view>
<view class="feed-bubble-image-container">
<image class="feed-bubble-post-image" data-originalurl="{{activeFeedBubbleSingle.thumbnail}}" bindtap="previewImage"
src="{{activeFeedBubbleSingle.thumbnail || '/images/map/dynamic_default.png'}}" mode="aspectFill"></image>
</view>
<!-- 底部操作栏 -->
<view class="feed-bubble-actions">
<view class="feed-bubble-action primary" bindtap="onFeedBubbleMoreTap"
data-lat="{{activeFeedBubbleSingle.location.latitude}}" data-lng="{{activeFeedBubbleSingle.location.longitude}}"
data-radius="{{activeFeedBubbleSingle.radius}}">
打开附近动态
</view>
</view>
<view class="feed-bubble-tip">轻触地图空白处即可收起</view>
</view>
</view>
<!-- 用户详情卡片 - 修复数据绑定 -->
<view class="user-card {{selectedUser ? 'show' : ''}}" wx:if="{{selectedUser}}"
style="bottom: {{safeAreaBottom + 260}}rpx;">
<view class="card-backdrop"></view>
<view class="card-content">
<view class="card-header">
<view class="card-avatar-url" wx:if="{{selectedUser.avatarUrl}}">
<image src="{{selectedUser.avatarUrl}}" data-avatar="{{selectedUser.originAvatarUrl}}" bindtap="previewImageAvatar"
mode="aspectFill" class="avatar-img" />
</view>
<view class="card-avatar" wx:else="{{selectedUser.avatarUrl}}">
</view>
<view class="card-info">
<text class="card-name">{{selectedUser.nickname || '用户'}}</text>
<text class="card-distance" wx:if="{{selectedUser.distance}}">距离 {{selectedUser.distance}}米</text>
<text class="card-distance" wx:else>位置信息</text>
<view class="card-status" wx:if="{{selectedUser.isOnline==true}}">
<view class="status-dot online"></view>
<text class="status-text">在线</text>
</view>
</view>
<view class="card-close" bindtap="closeUserCard">
<text class="close-icon">✕</text>
</view>
</view>
<view class="card-actions">
<view wx:if="{{isLoggedIn}}" class="action-btn chat-btn" bindtap="startChat" data-userid="{{selectedUser.userId}}"
data-nickName="{{selectedUser.nickname}}">
<view class="action-icon">💬</view>
<text class="action-text">聊天</text>
</view>
<view wx:if="{{isLoggedIn && !selectedUser.isFriend}}" class="action-btn add-btn" bindtap="addFriend"
data-userid="{{selectedUser.customId}}">
<view class="action-icon"></view>
<text class="action-text">加好友</text>
</view>
<view wx:if="{{isLoggedIn}}" class="action-btn profile-btn" bindtap="checkFriendRelation"
data-userid="{{selectedUser.customId}}">
<view class="action-icon">👤</view>
<text class="action-text">资料</text>
</view>
<view wx:if="{{!isLoggedIn}}" class="action-btn login-btn" bindtap="navigateToLogin">
<view class="action-icon">🔒</view>
<text class="action-text">登录</text>
</view>
</view>
</view>
</view>
<!-- 加载提示 - 优化设计 -->
<view class="loading-overlay" wx:if="{{!amapReady || (!latitude && !longitude)}}">
<view class="loading-content">
<view class="loading-spinner">
<view class="spinner-ring"></view>
<view class="spinner-ring"></view>
<view class="spinner-ring"></view>
</view>
<text class="loading-text">{{loadingText}}</text>
<text class="loading-subtitle">正在连接位置服务...</text>
</view>
</view>
<!-- POI详情卡片最上层 -->
<view class="user-card {{poiDetailShow ? 'show' : ''}}" wx:if="{{poiDetailShow}}"
style="bottom: {{safeAreaBottom + 140}}px; z-index:9999;">
<view class="card-backdrop"></view>
<view class="card-content">
<view class="card-header">
<view class="card-avatar poi-avatar">
<image wx:if="{{poiDetail.imageUrl}}" src="{{poiDetail.imageUrl}}" mode="aspectFill" />
<text wx:else class="card-avatar-text">📍</text>
</view>
<view class="card-info">
<text class="card-name">{{poiDetail.name || 'POI'}}</text>
<text class="card-distance">{{poiDetailAddress}}</text>
</view>
<view class="card-close" bindtap="closePoiCard">
<text class="close-icon">✕</text>
</view>
</view>
<view class="card-actions">
<view wx:if="{{isLoggedIn}}" data-poiDetail="{{poiDetail}}" class="action-btn" bindtap="onPoiFavorite">
<view class="action-icon">⭐</view>
<text class="action-text">{{mapClickCollect}}</text>
</view>
<view class="action-btn" bindtap="onPoiNavigate">
<view class="action-icon">🧭</view>
<text class="action-text">导航</text>
</view>
<view wx:if="{{!isLoggedIn}}" class="action-btn login-btn" bindtap="navigateToLogin">
<view class="action-icon">🔒</view>
<text class="action-text">登录</text>
</view>
</view>
</view>
</view>
<!-- POI提醒操作弹窗 -->
<view class="user-card show" wx:if="{{showPoiRemindModal}}" style="bottom: {{safeAreaBottom + 140}}px; z-index:10000;">
<view class="card-backdrop"></view>
<view class="card-content">
<view class="remind-title-block">
<text class="remind-title">地点设置</text>
<text class="remind-subtitle">到达或离开该地点时提醒你和好友</text>
</view>
<view class="card-header">
<view class="card-avatar">
<text class="card-avatar-text">POI</text>
</view>
<view class="card-info">
<!-- 名称可编辑 -->
<view class="card-name-editable">
<input class="card-name-input" value="{{lastPoiForRemind.name}}" placeholder="请输入地点名称"
bindinput="onPoiRemindNameInput" />
<view class="card-name-tip">可点击编辑名称</view>
</view>
<text class="card-distance">{{lastPoiForRemind.address || '详细地址未知'}}</text>
</view>
<view class="card-actions-right">
<button class="remind-save-btn" size="mini" type="primary" bindtap="onSavePoiRemind">保存</button>
<view class="card-close" bindtap="closePoiRemindModal">
<text class="close-icon">✕</text>
</view>
</view>
</view>
<!-- 好友选择与提醒模式 -->
<view class="remind-friends-mode-row">
<view class="remind-friends-block">
<button class="friend-select-btn" size="mini" type="primary" bindtap="onOpenFriendSelectModal">选择好友</button>
<view class="remind-friends-avatars">
<block wx:for="{{[0,1,2,3,4]}}" wx:key="index">
<view class="friend-avatar-mini">
<image wx:if="{{poiRemindSelectedFriends[index] && poiRemindSelectedFriends[index].avatarUrl}}"
src="{{poiRemindSelectedFriends[index].avatarUrl}}" class="avatar-img-mini" />
<text wx:elif="{{poiRemindSelectedFriends[index]}}" class="avatar-txt-mini">{{poiRemindSelectedFriends[index].nickname ?
poiRemindSelectedFriends[index].nickname.charAt(0) : 'U'}}</text>
<text wx:else class="avatar-txt-mini avatar-placeholder">+</text>
</view>
</block>
</view>
</view>
<view class="remind-mode-block">
<checkbox-group class="remind-mode-checkbox" bindchange="onPoiRemindModeChange" value="{{poiRemindMode}}">
<label class="remind-mode-label">
<checkbox value="arrive" name="arrive" />到达
</label>
<label class="remind-mode-label">
<checkbox value="leave" name="leave" />离开
</label>
</checkbox-group>
</view>
</view>
<view class="remind-slider-block" style="flex-direction: column; align-items: stretch; gap: 8px;">
<view style="display: flex; align-items: center; justify-content: space-between;">
<text class="remind-label">提醒范围</text>
<text class="remind-value highlight">{{poiRemindRadius}} 米</text>
</view>
<slider min="100" max="1000" step="10" value="{{poiRemindRadius}}" show-value="false"
bindchange="onPoiRemindRadiusChange" />
</view>
<view class="remind-desc">拖动滑块,地图上圆圈范围会实时变化</view>
</view>
</view>
<!-- 好友选择弹窗 -->
<view class="friend-select-modal" wx:if="{{showFriendSelectModal}}">
<view class="friend-select-content">
<view class="friend-select-header">
<view class="friend-select-title">选择好友最多3个</view>
<view class="friend-select-close" bindtap="onCloseFriendSelect">✕</view>
</view>
<!-- 已选好友横向展示 -->
<view class="friend-selected-row">
<block wx:for="{{[0,1,2]}}" wx:key="index">
<view class="friend-selected-avatar" wx:if="{{poiRemindSelectedFriends[index]}}"
bindtap="onRemoveSelectedFriend" data-userid="{{poiRemindSelectedFriends[index].userId}}">
<image wx:if="{{poiRemindSelectedFriends[index].avatarUrl}}"
src="{{poiRemindSelectedFriends[index].avatarUrl}}" class="avatar-img-mini" />
<text wx:else class="avatar-txt-mini">{{poiRemindSelectedFriends[index].nickname ?
poiRemindSelectedFriends[index].nickname.charAt(0) : 'U'}}</text>
<view class="friend-selected-remove">✕</view>
</view>
<view class="friend-selected-avatar friend-selected-placeholder" wx:else>+</view>
</block>
</view>
<!-- 搜索框 -->
<input class="friend-search-input" placeholder="搜索昵称" value="{{friendSearchText}}"
bindinput="onFriendSearchInput" />
<scroll-view scroll-y="true" class="friend-list-scroll">
<block wx:for="{{filteredFriendsList}}" wx:for-item="item" wx:key="userId">
<view
class="friend-item {{item.selected ? 'selected' : ''}} {{poiRemindSelectedFriends.length>=3 && !item.selected ? 'disabled' : ''}}"
bindtap="onToggleFriendSelect" data-userid="{{item.userId}}">
<image wx:if="{{item.avatarUrl}}" src="{{item.avatarUrl}}" class="friend-avatar" />
<view wx:else class="friend-avatar friend-avatar-txt">{{item.nickname ? item.nickname.charAt(0) : 'U'}}
</view>
<text class="friend-nickname">{{item.nickname}}</text>
<view class="friend-check" wx:if="{{item.selected}}">✔</view>
</view>
</block>
</scroll-view>
<button class="friend-select-done" type="primary" size="mini" bindtap="onFriendSelectDone"
disabled="{{poiRemindSelectedFriends.length===0}}">完成</button>
</view>
</view>
<!-- 地点标记弹窗(底部卡片) -->
<view class="location-mark-modal" wx:if="{{showLocationMarkModal}}">
<!-- 遮罩层,点击关闭 -->
<view class="location-mark-mask" bindtap="onCloseLocationMarkModal"></view>
<!-- 底部弹出卡片 -->
<view class="location-mark-sheet location-mark-sheet-animate">
<!-- 顶部手柄和关闭按钮 -->
<view class="location-mark-sheet-handle-row">
<view class="location-mark-sheet-handle"></view>
<view class="location-mark-sheet-close" bindtap="onCloseLocationMarkModal">✕</view>
</view>
<!-- 标题 -->
<view class="location-mark-sheet-title">地点标记</view>
<!-- 搜索框 -->
<view class="location-mark-search-row">
<text class="iconfont search-icon">🔍</text>
<input class="location-mark-search" placeholder="搜索收藏地址" value="{{locationMarkSearchText}}"
bindinput="onLocationMarkSearchInput" />
<text wx:if="{{locationMarkSearchText}}" class="iconfont clear-icon" bindtap="onClearLocationMarkSearch">✕</text>
</view>
<!-- 地址列表 -->
<scroll-view scroll-y class="location-mark-list-sheet">
<block wx:for="{{filteredLocationMarkList}}" wx:for-item="item" wx:key="id">
<view class="location-mark-item-card" bindtap="onLocationMarkItemTap" data-item="{{item}}">
<view class="location-mark-item-main-opt">
<!-- 左侧主信息 -->
<view class="location-mark-item-info-opt">
<view class="location-mark-name-opt">{{item.name}}</view>
<view class="location-mark-coord-opt">{{item.lat}}, {{item.lng}}</view>
</view>
<!-- 右上操作按钮 -->
<view class="location-mark-actions-opt">
<!-- 左侧主信息
<button class="location-mark-edit-btn-opt" size="mini" bindtap="onEditLocationMarkName" data-id="{{item.id}}">
<text class="iconfont">✏️</text> 修改
</button>
-->
<button class="location-mark-del-btn-opt" size="mini" bindtap="onDeleteLocationMark" data-id="{{item.id}}"
catchtap="onDeleteLocationMark">
<text class="iconfont">🗑️</text> 删除
</button>
</view>
</view>
<!-- 下方提醒好友和类型 -->
<view class="location-mark-meta-opt">
<view class="location-mark-friends-opt">
<block wx:for="{{item.remindFriends}}" wx:for-item="f" wx:key="userId">
<view class="location-mark-friend-avatar-opt">
<image wx:if="{{f.avatarUrl}}" src="{{f.avatarUrl}}" />
<text wx:else>{{f.nickname ? f.nickname.charAt(0) : 'U'}}</text>
</view>
</block>
<view class="location-mark-friend-btn-opt" bindtap="onSetRemindFriends" data-id="{{item.id}}"
catchtap="onSetRemindFriends">+</view>
</view>
<view class="location-mark-type-tag-opt {{item.remindType}}" bindtap="onToggleRemindType"
data-id="{{item.id}}" catchtap="onToggleRemindType">
{{item.remindType == 'arrive' ? '到达' : '离开'}}
</view>
</view>
</view>
</block>
<view wx:if="{{filteredLocationMarkList.length === 0}}" class="location-mark-empty">
<text class="iconfont empty-icon">📍</text>
<text>暂无收藏地址</text>
</view>
</scroll-view>
<!-- 加号浮动按钮 -->
<view class="location-mark-fab" bindtap="onAddLocationPlace">
<text class="location-mark-fab-icon">+</text>
</view>
</view>
</view>
<!-- POI周边列表弹窗 -->
<view class="poi-around-modal" wx:if="{{showPoiAroundModal}}">
<view class="poi-around-mask" bindtap="onClosePoiAroundModal"></view>
<view class="poi-around-sheet">
<!-- 右上角关闭按钮 -->
<view class="poi-around-close-x" bindtap="onClosePoiAroundModal">✕</view>
<view class="poi-around-title">附近地点</view>
<scroll-view scroll-y class="poi-around-list">
<block wx:for="{{poiAroundList}}" wx:for-item="item" wx:key="id">
<view class="poi-around-item" bindtap="onPoiAroundItemTap" data-item="{{item}}">
<view class="poi-around-name">{{item.name}}</view>
<view class="poi-around-address">{{item.address}}</view>
<view class="poi-around-distance">{{item.distanceStr}}</view>
</view>
</block>
<view wx:if="{{poiAroundList.length === 0}}" class="poi-around-empty">暂无数据</view>
</scroll-view>
<view class="poi-around-close-btn" bindtap="onClosePoiAroundModal">关闭</view>
</view>
</view>
<!-- 商家信息弹窗-->
<view wx:if="{{merchantInfoModalVisible}}" class="merchant-info-modal" catchtap="closeMerchantInfo">
<view class="merchant-info-card" catchtap="preventClose">
<button class="close-btn-abs" bindtap="closeMerchantInfo" aria-label="关闭">
<text class="close-icon">×</text>
</button>
<!-- 菜品信息区域 -->
<view wx:if="{{selectedMerchant.dishInfo}}" class="dish-info-container">
<!-- 左侧:菜品宣传图 -->
<view class="dish-image-row">
<image class="dish-image" src="{{selectedMerchant.dishInfo.image}}" mode="aspectFill"></image>
<!-- 右侧:菜品详情 -->
<view class="dish-detail">
<!-- 第一行:标题 -->
<view class="dish-title-row">
<text class="dish-title">{{selectedMerchant.name}}</text>
</view>
<view class="dish-description-row">
<text class="dish-description">{{selectedMerchant.dishInfo.title}}</text>
</view>
<!-- 第二行:销售数据和排名 -->
<view class="dish-sales-row">
<text class="dish-sales">{{selectedMerchant.dishInfo.sales}}</text>
<text class="dish-ranking">{{selectedMerchant.dishInfo.ranking}}</text>
</view>
<!-- 第三行:评分和店铺信息 -->
<view class="dish-rating-row">
<view class="dish-rating-left">
<text class="dish-rating">{{selectedMerchant.dishInfo.rating}} 分</text>
<text class="dish-shop-name">{{selectedMerchant.dishInfo.shopName}}</text>
</view>
<text class="dish-district">{{selectedMerchant.dishInfo.district}}</text>
</view>
</view>
</view>
<!-- 第四行:价格信息 -->
<view class="dish-price-row">
<view class="dish-price-left">
<view class="dish-group-price">¥{{selectedMerchant.dishInfo.groupPrice}}<text class="dish-original-price">¥{{selectedMerchant.dishInfo.originalPrice}}</text></view>
<view class="dish-discount">(团购价)<text>省{{selectedMerchant.dishInfo.discount}}元</text></view>
</view>
<image class="dish-go-btn" src="/images/merchant/go.png" mode="aspectFit" catchtap="onDishGoClick"></image>
</view>
<!-- 第5行详细地址 -->
<view class="dish-info-address">详细地址:{{selectedMerchant.address}}</view>
</view>
</view>
</view>
<!-- 地址搜索结果列表选择时弹窗 -->
<view wx:if="{{searchResultInfoModalVisible}}" class="result-info-modal"
bindtouchstart="onTouchStart"
bindtouchmove="onTouchMove"
bindtouchend="onTouchEnd"
style="transform: translateY({{modalTranslateY}}px); transition: transform 0.3s ease;">
<view class="result-info-card">
<view class="result-menu-item" bindtap="handleHideBottm">
<image src="/images/map/bottom_top.png" />
</view>
<view class="merchant-info-row merchant-info-meta">
<text class="merchant-info-meta-text">位置:{{merchantName}}</text>
</view>
<view class="merchant-info-row merchant-info-meta">
<text class="merchant-info-meta-content">详细地址:{{merchant}}</text>
</view>
<view class="merchant-actions">
<image class="merchant-actions-img" src="/images/map/navigate- map.png" bindtap="onNavigation"></image>
<image class="merchant-actions-img" src="/images/map/share-map.png" bindtap="onSharechant"></image>
<image wx:if="{{!addressIsFavorited}}" class="merchant-actions-img" src="/images/map/collect-map.png"
bindtap="onAddressCollect"></image>
<image wx:else class="merchant-actions-img" src="/images/map/collected.png" bindtap="onAddressCollect"></image>
</view>
</view>
</view>
<!-- 底部分享弹窗 -->
<view class="result-info-modal" wx:if="{{shareShareVisible}}"
bindtouchstart="onTouchStart"
bindtouchmove="onTouchMove"
bindtouchend="onTouchEnd"
style="transform: translateY({{modalTranslateY}}px); transition: transform 0.3s ease;"
>
<view class="result-info-card">
<!-- 顶部关闭按钮 -->
<view class="result-menu-item" bindtap="handleHideShareBottm">
<image src="/images/map/bottom_top.png" />
</view>
<view class="result-info-title">
<text>分享给好友</text>
</view>
<!-- 好友列表(横向滑动) -->
<view class="share-friends-scroll">
<!-- 横向滚动容器 -->
<scroll-view scroll-x class="share-friends-list-share" scroll-with-animation>
<!-- 好友项 -->
<view class="friend-item-share" wx:for="{{friendsData}}" wx:key="id">
<!-- 头像容器 -->
<view class="avatar-container-share">
<image src="{{item.avatar}}" class="friend-avatar-share" mode="cover" bindtap="startChat"
data-nickName="{{item.nickname}}" data-userid="{{item.customId}}" />
</view>
<!-- 名称文本,自动处理过长情况 -->
<text class="friend-name-share">{{item.nickname}}</text>
</view>
</scroll-view>
</view>
<!-- 分享选项(自动换行) -->
<view class="share-options">
<view class="option-item" wx:for="{{shareOptions}}" wx:key="type" data-type="{{item.type}}">
<block wx:if="{{item.type=='wechat'}}">
<button class="action-btn-share" open-type="share">
<image src="/images/map/Wechat_logo.png"></image>
</button>
</block>
<block wx:else>
<image src="{{item.icon}}" class="option-icon" mode="aspectFit" data-type="{{item.type}}"
bindtap="handleShare" />
</block>
</view>
</view>
</view>
</view>
<!-- 点击搜索结果弹窗的导航按钮 -->
<view wx:if="{{searchResultNavigationVisible}}" class="result-info-modal" bindtouchstart="onTouchStart" bindtouchmove="onTouchMove"
bindtouchend="onTouchEnd"
style="transform: translateY({{modalTranslateY}}px); transition: transform 0.3s ease;">
<view class="result-info-card">
<view class="result-menu-item" bindtap="handleHideBottmNavigation">
<image src="/images/map/bottom_top.png" />
</view>
<view class="merchant-info-row merchant-info-meta">
<text class="merchant-address">距离你{{distance}}</text>
</view>
<view class="merchant-info-row merchant-info-meta">
<text class="merchant-info-meta-content">详细地址:{{merchant}}</text>
</view>
<view class="merchant-actions">
<!-- 高德图标+文字组合 -->
<view class="action-item" bindtap="onNavigationTap" data-type="gaode">
<image class="merchant-navigation-img" src="/images/map/gaodemap_logo.png"></image>
<text class="action-text-navigation">高德地图</text>
</view>
<view class="action-item" bindtap="onNavigationTap" data-type="baidu">
<image class="merchant-navigation-img" src="/images/map/baidumap_logo.png"></image>
<text class="action-text-navigation">百度地图</text>
</view>
<view class="action-item" bindtap="onNavigationTap" data-type="tengxun">
<image class="merchant-navigation-img" src="/images/map/tengxunmap_logo.png"></image>
<text class="action-text-navigation">腾讯地图</text>
</view>
</view>
<view>
<image class="image-getaddress" bindtap="onNavigationTap" src="/images/map/get_address.png" />
</view>>
</view>
</view>