wodexingcheng.wxml 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512
  1. <view class="container">
  2. <!-- 顶部导航 -->
  3. <view class="header">
  4. <text class="title">我的行程</text>
  5. </view>
  6. <!-- 选项卡 -->
  7. <view class="tabs">
  8. <view
  9. class="tab {{activeTab === 'in_progress' ? 'active' : ''}}"
  10. bindtap="switchTab"
  11. data-tab="in_progress"
  12. >
  13. 进行中
  14. </view>
  15. <view
  16. class="tab {{activeTab === 'all' ? 'active' : ''}}"
  17. bindtap="switchTab"
  18. data-tab="all"
  19. >
  20. 未完成
  21. </view>
  22. <view
  23. class="tab {{activeTab === 'completed' ? 'active' : ''}}"
  24. bindtap="switchTab"
  25. data-tab="completed"
  26. >
  27. 已完成
  28. </view>
  29. </view>
  30. <!-- 进行中行程 -->
  31. <block wx:if="{{activeTab === 'in_progress'}}">
  32. <block wx:if="{{inProgressPlans.length > 0}}">
  33. <view class="plan-result">
  34. <!-- 地图总览 -->
  35. <view class="map-section" wx:if="{{latestPlanMapData.showMap}}">
  36. <view class="section-header">
  37. <image src="/images/icons/map-red.png" class="section-icon"></image>
  38. <text class="section-title">行程地图总览</text>
  39. </view>
  40. <!-- 天数切换标签 -->
  41. <scroll-view scroll-x class="day-tabs">
  42. <view
  43. class="day-tab {{currentMapDay === -1 ? 'active' : ''}}"
  44. bindtap="resetToAllAttractions"
  45. >
  46. 全部
  47. </view>
  48. <view
  49. wx:for="{{inProgressPlans[0].day_plans}}"
  50. wx:key="day"
  51. class="day-tab {{currentMapDay === index ? 'active' : ''}}"
  52. bindtap="switchMapDay"
  53. data-day="{{index}}"
  54. style="border-color: {{['#e54d42','#f37b1d','#1cbbb4','#0081ff','#6739b6','#9c26b0','#e03997'][index]}}; color: {{currentMapDay === index ? '#fff' : ['#e54d42','#f37b1d','#1cbbb4','#0081ff','#6739b6','#9c26b0','#e03997'][index]}}; background-color: {{currentMapDay === index ? ['#e54d42','#f37b1d','#1cbbb4','#0081ff','#6739b6','#9c26b0','#e03997'][index] : 'transparent'}}"
  55. >
  56. 第{{item.day_number}}天
  57. </view>
  58. </scroll-view>
  59. <!-- 地图容器 -->
  60. <view class="map-container">
  61. <map
  62. id="latestPlanMap"
  63. longitude="{{latestPlanMapData.longitude}}"
  64. latitude="{{latestPlanMapData.latitude}}"
  65. scale="{{latestPlanMapData.scale || 14}}"
  66. markers="{{latestPlanMapData.markers}}"
  67. polyline="{{latestPlanMapData.polylines}}"
  68. include-points="{{latestPlanMapData.includePoints}}"
  69. style="width: 100%; height: 400px;"
  70. bindmarkertap="handleMarkerTap"
  71. >
  72. <!-- 地图控制按钮 -->
  73. <cover-view class="map-controls">
  74. <cover-button class="control-btn" bindtap="handleZoomIn">
  75. <image src="/images/icons/zoom-in.png" class="control-icon"></image>
  76. </cover-button>
  77. <cover-button class="control-btn" bindtap="handleZoomOut">
  78. <image src="/images/icons/zoom-out.png" class="control-icon"></image>
  79. </cover-button>
  80. <cover-button class="control-btn" bindtap="resetToAllAttractions">
  81. <image src="/images/icons/location.png" class="control-icon"></image>
  82. </cover-button>
  83. </cover-view>
  84. <!-- 路线图例 -->
  85. <cover-view class="map-legend">
  86. <cover-view wx:for="{{inProgressPlans[0].day_plans}}" wx:key="day" class="legend-item">
  87. <cover-view class="legend-color" style="background:{{['#e54d42','#f37b1d','#1cbbb4','#0081ff','#6739b6','#9c26b0','#e03997'][index]}}"></cover-view>
  88. <cover-text>第{{item.day_number}}天</cover-text>
  89. </cover-view>
  90. </cover-view>
  91. </map>
  92. </view>
  93. <!-- 地图图例 -->
  94. <view class="map-legend">
  95. <view class="legend-item">
  96. <image src="/images/marker-red-star.png" class="legend-icon"></image>
  97. <text>红色教育基地</text>
  98. </view>
  99. <view class="legend-item">
  100. <image src="/images/map-line-sample.png" class="legend-icon"></image>
  101. <text>行程路线</text>
  102. </view>
  103. </view>
  104. </view>
  105. <!-- 路线规划展示 -->
  106. <view class="route-plan-section" wx:if="{{latestPlanMapData.showMap}}">
  107. <view class="section-header">
  108. <image src="/images/icons/route-red.png" class="section-icon"></image>
  109. <text class="section-title">行程详情</text>
  110. </view>
  111. <view class="day-routes">
  112. <view wx:for="{{inProgressPlans[0].day_plans}}" wx:key="day" class="day-route">
  113. <view class="route-header">
  114. <view class="route-day-tag" style="background-color: {{['#e54d42','#f37b1d','#1cbbb4','#0081ff','#6739b6','#9c26b0','#e03997'][index%7]}}">
  115. 第{{item.day_number}}天
  116. </view>
  117. <text class="route-theme">{{item.theme}}</text>
  118. </view>
  119. <!-- 景点列表 -->
  120. <view class="route-steps">
  121. <view wx:for="{{item.spots}}" wx:key="id" wx:for-item="spot" wx:for-index="spotIndex" class="route-step">
  122. <view class="step-marker" style="background-color: {{['#e54d42','#f37b1d','#1cbbb4','#0081ff','#6739b6','#9c26b0','#e03997'][index%7]}}">
  123. {{spotIndex+1}}
  124. <image wx:if="{{spot.has_checked}}" src="/images/icons/checked.png" class="checked-icon"></image>
  125. </view>
  126. <view class="step-content">
  127. <view class="step-main">
  128. <view class="step-header">
  129. <text class="step-title">{{spot.name}}</text>
  130. <view class="step-tag" wx:if="{{spot.type}}">{{spot.type}}</view>
  131. </view>
  132. <view class="step-info">
  133. <view class="info-item">
  134. <text>{{spot.visit_time}} · {{spot.duration}}分钟</text>
  135. </view>
  136. <view class="info-item">
  137. <image src="/images/icons/location.png" class="info-icon"></image>
  138. <text>{{spot.address}}</text>
  139. </view>
  140. </view>
  141. </view>
  142. <!-- 在打卡按钮下方添加图片预览 -->
  143. <view class="step-actions-vertical">
  144. <button class="action-btn detail-btn" bindtap="showSpotDetail" data-day="{{index}}" data-spot="{{spotIndex}}" data-spotid="{{spot.id}}">
  145. 详 情
  146. </button>
  147. <button class="action-btn check-btn {{spot.has_checked ? 'checked' : ''}}" catchtap="checkInSpot" data-day="{{index}}" data-spot="{{spotIndex}}" data-spotid="{{spot.id}}">
  148. {{spot.has_checked ? '已打卡' : '打 卡'}}
  149. </button>
  150. <!-- 打卡图片预览 -->
  151. <view wx:if="{{spot.checkin_images && spot.checkin_images.length > 0}}" class="checkin-images">
  152. <image wx:for="{{spot.checkin_images}}" wx:key="*this" src="{{item}}" mode="aspectFill" class="checkin-image"></image>
  153. </view>
  154. </view>
  155. </view>
  156. </view>
  157. </view>
  158. <view class="route-summary">
  159. <image src="/images/icons/summary-red.png" class="summary-icon"></image>
  160. <text class="summary-text">{{item.summary}}</text>
  161. </view>
  162. </view>
  163. </view>
  164. </view>
  165. <!-- 操作按钮 -->
  166. <view class="action-buttons">
  167. <button class="view-btn" bindtap="completePlan" data-id="{{inProgressPlans[0].id}}">
  168. <image src="/images/icons/view-details.png" class="btn-icon"></image>
  169. 行程结束并保存
  170. </button>
  171. <button class="share-btn" bindtap="sharePlan" data-id="{{inProgressPlans[0].id}}">
  172. <image src="/images/icons/share-red.png" class="btn-icon"></image>
  173. 分享行程
  174. </button>
  175. </view>
  176. </view>
  177. </block>
  178. <block wx:else>
  179. <view class="empty-state">
  180. <image src="/images/empty-plan.png" mode="aspectFit"></image>
  181. <text>您没有进行中的行程</text>
  182. <button class="primary-btn" bindtap="navigateToCreate">开始规划新行程</button>
  183. </view>
  184. </block>
  185. </block>
  186. <!-- 已完成行程 -->
  187. <block wx:if="{{activeTab === 'completed'}}">
  188. <view class="history-container">
  189. <block wx:if="{{completedPlans.length > 0}}">
  190. <!-- 行程卡片列表 -->
  191. <view class="plan-list">
  192. <block wx:for="{{completedPlans}}" wx:key="id">
  193. <view class="plan-card" data-id="{{item.id}}">
  194. <!-- 状态标签 -->
  195. <view class="status-tag {{item.status === 'in_progress' ? 'in-progress' : 'completed'}}">
  196. {{item.status === 'in_progress' ? '进行中' : '已完成'}}
  197. </view>
  198. <!-- 卡片顶部装饰条 -->
  199. <view class="card-ribbon">
  200. </view>
  201. <view class="card-content">
  202. <!-- 行程标题和城市 -->
  203. <view class="plan-header">
  204. <view class="city-tags">
  205. <block wx:for="{{item.cities}}" wx:key="id">
  206. <view class="city-tag">{{item.name}}</view>
  207. </block>
  208. </view>
  209. <text class="plan-title">{{item.title}}</text>
  210. </view>
  211. <!-- 行程描述 -->
  212. <view class="plan-content">
  213. <text class="plan-desc">{{item.description}}</text>
  214. <!-- 统计信息 -->
  215. <view class="plan-stats">
  216. <view class="stat-item">
  217. <image class="stat-icon" src="/images/icons/flag-red.png"></image>
  218. <text>{{item.statistics.total_attractions}}个景点</text>
  219. </view>
  220. <view class="stat-item">
  221. <image class="stat-icon" src="/images/icons/calendar-red.png"></image>
  222. <text>{{item.created_at}}</text>
  223. </view>
  224. </view>
  225. </view>
  226. </view>
  227. <!-- 底部操作区域 -->
  228. <view class="card-footer">
  229. <button class="action-btn share-btn" catchtap="sharePlan" data-id="{{item.id}}">
  230. <image src="/images/icons/share-white.png" class="btn-icon"></image>
  231. 分享
  232. </button>
  233. <button class="action-btn detail-btn" catchtap="navigateToDetail" data-id="{{item.id}}">
  234. <image src="/images/eye-icon.png" class="btn-icon"></image>
  235. 查看详情
  236. </button>
  237. </view>
  238. </view>
  239. </block>
  240. </view>
  241. <!-- 分页控件 -->
  242. <view class="pagination-container">
  243. <view class="pagination">
  244. <button
  245. class="pagination-btn prev"
  246. disabled="{{completedCurrentPage === 1}}"
  247. bindtap="changeCompletedPage"
  248. data-page="{{completedCurrentPage - 1}}"
  249. >
  250. 上一页
  251. </button>
  252. <view class="page-indicator">
  253. <text class="current-page">{{completedCurrentPage}}</text>
  254. <text class="page-separator">/</text>
  255. <text class="total-pages">{{completedTotalPages}}</text>
  256. </view>
  257. <button
  258. class="pagination-btn next"
  259. disabled="{{completedCurrentPage === completedTotalPages}}"
  260. bindtap="changeCompletedPage"
  261. data-page="{{completedCurrentPage + 1}}"
  262. >
  263. 下一页
  264. </button>
  265. </view>
  266. </view>
  267. </block>
  268. <!-- 空状态 -->
  269. <block wx:else>
  270. <view class="empty-state">
  271. <image src="/images/empty-plan.png" mode="aspectFit" class="empty-illustration"></image>
  272. <text class="empty-title">暂无已完成行程</text>
  273. <text class="empty-subtitle">您还没有完成任何行程</text>
  274. <button class="create-btn" bindtap="navigateToCreate">
  275. 立即规划新行程
  276. </button>
  277. </view>
  278. </block>
  279. </view>
  280. </block>
  281. <!-- 全部行程 -->
  282. <block wx:if="{{activeTab === 'all'}}">
  283. <view class="history-container">
  284. <block wx:if="{{allPlans.length > 0}}">
  285. <!-- 行程卡片列表 -->
  286. <view class="plan-list">
  287. <block wx:for="{{allPlans}}" wx:key="id">
  288. <view class="plan-card" data-id="{{item.id}}">
  289. <!-- 状态标签 -->
  290. <view class="status-tag {{item.status === 'in_progress' ? 'in-progress' : 'completed'}}">
  291. {{item.status === 'in_progress' ? '进行中' : '已完成'}}
  292. </view>
  293. <!-- 卡片顶部装饰条 -->
  294. <view class="card-ribbon">
  295. </view>
  296. <view class="card-content">
  297. <!-- 行程标题和城市 -->
  298. <view class="plan-header">
  299. <view class="city-tags">
  300. <block wx:for="{{item.cities}}" wx:key="id">
  301. <view class="city-tag">{{item.name}}</view>
  302. </block>
  303. </view>
  304. <text class="plan-title">{{item.title}}</text>
  305. </view>
  306. <!-- 行程描述 -->
  307. <view class="plan-content">
  308. <text class="plan-desc">{{item.description}}</text>
  309. <!-- 统计信息 -->
  310. <view class="plan-stats">
  311. <view class="stat-item">
  312. <image class="stat-icon" src="/images/icons/flag-red.png"></image>
  313. <text>{{item.statistics.total_attractions}}个景点</text>
  314. </view>
  315. <view class="stat-item">
  316. <image class="stat-icon" src="/images/icons/calendar-red.png"></image>
  317. <text>{{item.created_at}}</text>
  318. </view>
  319. </view>
  320. </view>
  321. </view>
  322. <!-- 底部操作区域 -->
  323. <view class="card-footer">
  324. <button class="action-btn share-btn" catchtap="sharePlan" data-id="{{item.id}}">
  325. <image src="/images/icons/share-white.png" class="btn-icon"></image>
  326. 分享
  327. </button>
  328. <button
  329. class="action-btn {{item.status === 'in_progress' ? 'start-btn' : 'detail-btn'}}"
  330. catchtap="{{item.status === 'in_progress' ? 'startPlan' : 'navigateToDetail'}}"
  331. data-id="{{item.id}}"
  332. >
  333. <image
  334. src="{{item.status === 'in_progress' ? '/images/icons/play.png' : '/images/eye-icon.png'}}"
  335. class="btn-icon"
  336. ></image>
  337. {{item.status === 'in_progress' ? '开始行程' : '查看详情'}}
  338. </button>
  339. </view>
  340. </view>
  341. </block>
  342. </view>
  343. <!-- 分页控件 -->
  344. <view class="pagination-container">
  345. <view class="pagination">
  346. <button
  347. class="pagination-btn prev"
  348. disabled="{{allCurrentPage === 1}}"
  349. bindtap="changeAllPage"
  350. data-page="{{allCurrentPage - 1}}"
  351. >
  352. 上一页
  353. </button>
  354. <view class="page-indicator">
  355. <text class="current-page">{{allCurrentPage}}</text>
  356. <text class="page-separator">/</text>
  357. <text class="total-pages">{{allTotalPages}}</text>
  358. </view>
  359. <button
  360. class="pagination-btn next"
  361. disabled="{{allCurrentPage === allTotalPages}}"
  362. bindtap="changeAllPage"
  363. data-page="{{allCurrentPage + 1}}"
  364. >
  365. 下一页
  366. </button>
  367. </view>
  368. </view>
  369. </block>
  370. <!-- 空状态 -->
  371. <block wx:else>
  372. <view class="empty-state">
  373. <image src="/images/empty-plan.png" mode="aspectFit" class="empty-illustration"></image>
  374. <text class="empty-title">暂无行程记录</text>
  375. <text class="empty-subtitle">您还没有创建任何行程</text>
  376. <button class="create-btn" bindtap="navigateToCreate">
  377. 立即规划新行程
  378. </button>
  379. </view>
  380. </block>
  381. </view>
  382. </block>
  383. <!-- 景点详情弹窗 -->
  384. <view class="modal" wx:if="{{showSpotModal}}">
  385. <view class="modal-mask" catchtap="hideSpotModal"></view>
  386. <view class="modal-content">
  387. <view class="modal-header">
  388. <text class="modal-title">{{currentSpot.name}}</text>
  389. <image src="/images/icons/close-circle.png" class="close-icon" catchtap="hideSpotModal"></image>
  390. </view>
  391. <scroll-view class="modal-body" scroll-y>
  392. <image src="{{currentSpot.image || '/images/default-spot.png'}}" class="spot-image" mode="widthFix"></image>
  393. <view class="spot-info">
  394. <view class="info-item">
  395. <image src="/images/icons/clock.png" class="info-icon"></image>
  396. <text>参观时间: {{currentSpot.visit_time}}</text>
  397. </view>
  398. <view class="info-item">
  399. <image src="/images/icons/duration.png" class="info-icon"></image>
  400. <text>预计时长: {{currentSpot.duration}}分钟</text>
  401. </view>
  402. <view class="info-item">
  403. <image src="/images/icons/location.png" class="info-icon"></image>
  404. <text>{{currentSpot.address}}</text>
  405. </view>
  406. </view>
  407. <view class="spot-desc">
  408. <text class="desc-title">景点介绍</text>
  409. <text class="desc-content">{{currentSpot.description || '暂无详细介绍'}}</text>
  410. </view>
  411. <view class="spot-desc">
  412. <text class="desc-title">历史意义</text>
  413. <text class="desc-content">{{currentSpot.history_significance || '暂无详细介绍'}}</text>
  414. </view>
  415. </scroll-view>
  416. <view class="modal-footer">
  417. <button class="modal-btn check-btn" catchtap="checkInSpot" data-day="{{currentDayIndex}}" data-spot="{{currentSpotIndex}}" data-spotid="{{currentSpot.id}}">
  418. <image src="/images/icons/check-in.png" class="action-icon"></image>
  419. {{currentSpot.has_checked ? '已打卡' : '打卡'}}
  420. </button>
  421. <button class="modal-btn nav-btn" catchtap="navigateToSpot">
  422. <image src="/images/icons/navigation.png" class="action-icon"></image>
  423. 导航前往
  424. </button>
  425. </view>
  426. </view>
  427. </view>
  428. <!-- 打卡弹窗 -->
  429. <view class="modal" wx:if="{{showCheckinModal}}">
  430. <view class="modal-mask" catchtap="closeCheckinModal"></view>
  431. <view class="modal-content checkin-modal">
  432. <view class="modal-header">
  433. <text class="modal-title">{{tempCheckinData.isEdit ? '编辑打卡' : '打卡记录'}}</text>
  434. <image src="/images/icons/close-circle.png" class="close-icon" catchtap="closeCheckinModal"></image>
  435. </view>
  436. <scroll-view class="modal-body" scroll-y>
  437. <!-- 打卡图片 -->
  438. <view class="checkin-image-section">
  439. <text class="section-label">打卡照片</text>
  440. <view class="image-uploader" bindtap="chooseCheckinImage">
  441. <block wx:if="{{checkinImage}}">
  442. <image src="{{checkinImage}}" mode="aspectFill" class="uploaded-image"></image>
  443. </block>
  444. <block wx:else>
  445. <image src="/images/icons/camera-add.png" class="upload-icon"></image>
  446. <text class="upload-text">点击上传照片</text>
  447. </block>
  448. <view class="uploading-mask" wx:if="{{isUploading}}">
  449. <image src="/images/icons/loading.png" class="loading-icon"></image>
  450. </view>
  451. </view>
  452. </view>
  453. <!-- 打卡文案 -->
  454. <view class="checkin-note-section">
  455. <text class="section-label">打卡心得</text>
  456. <textarea
  457. class="note-textarea"
  458. placeholder="写下你的参观心得..."
  459. maxlength="200"
  460. value="{{checkinNote}}"
  461. bindinput="onCheckinNoteInput"
  462. ></textarea>
  463. <text class="word-count">{{checkinNote.length}}/200</text>
  464. </view>
  465. </scroll-view>
  466. <view class="modal-footer">
  467. <button class="modal-btn cancel-btn" catchtap="closeCheckinModal">取消</button>
  468. <button class="modal-btn confirm-btn" catchtap="submitCheckin">
  469. {{tempCheckinData.isEdit ? '更新打卡' : '提交打卡'}}
  470. </button>
  471. </view>
  472. </view>
  473. </view>
  474. </view>