{"id":371,"date":"2026-01-28T10:35:35","date_gmt":"2026-01-28T02:35:35","guid":{"rendered":"https:\/\/timee.love\/?p=371"},"modified":"2026-03-02T17:54:16","modified_gmt":"2026-03-02T09:54:16","slug":"%e7%9c%8b%e7%9c%8b%e4%bd%a0%e5%92%8c%e9%92%9b%e5%bc%a5%e4%b9%8b%e9%97%b4%e6%9c%89%e5%a4%9a%e8%bf%9c","status":"publish","type":"post","link":"https:\/\/timee.love\/?p=371","title":{"rendered":"\u770b\u770b\u4f60\u548c\u949b\u5f25\u4e4b\u95f4\u6709\u591a\u8fdc"},"content":{"rendered":"\n<p>\u60f3\u77e5\u9053\u73b0\u5728\u548c\u949b\u5f25\u4e4b\u95f4\u7684\u76f4\u7ebf\u8ddd\u79bb\u6709\u591a\u8fdc\u5417\uff1f\u70b9\u51fb\u83b7\u53d6\u4f4d\u7f6e\u6309\u94ae\u770b\u770b\u5427\uff01<\/p>\n\n\n\n<div style=\"height:25px\" aria-hidden=\"true\" class=\"wp-block-spacer\"><\/div>\n\n\n\n<div id=\"distance-module\">\n  <div class=\"distance-header\">\n    <h2>\u949b\u5f25\u4f4d\u7f6e\u8ba1\u7b97\u673a<\/h2>\n    <p class=\"subtitle\">\ud83e\udd65\u548c\u949b\u5f25\u79bb\u591a\u8fdc<\/p>\n  <\/div>\n  \n  <div class=\"distance-body\">\n    <button id=\"get-location-btn\" class=\"location-btn\">\n      <span class=\"btn-icon\">\ud83d\udccd<\/span>\n      <span class=\"btn-text\">\u83b7\u53d6\u6211\u7684\u4f4d\u7f6e<\/span>\n    <\/button>\n        <div class=\"distance-label\" id=\"result\">\u8ddd\u79bbTIMEE<\/div>\n    <div class=\"distance-result\">\n      <div class=\"distance-value\" id=\"distance-value\">&#8212;<\/div>\n      <div class=\"distance-unit\" id=\"distance-unit\">km<\/div>\n    <\/div>\n    \n\n    \n    <div class=\"location-info\" style=\"display:none;\">\n      <div class=\"info-item\">\n        <span class=\"info-label\">\u6211\u7684\u4f4d\u7f6e\uff1a<\/span>\n        <span class=\"info-value\" id=\"user-location\">\u672a\u83b7\u53d6<\/span>\n      <\/div>\n      <div class=\"info-item\">\n        <span class=\"info-label\">TIMEE\u4f4d\u7f6e\uff1a<\/span>\n        <span class=\"info-value\">\u5408\u80a5\u5e02<\/span>\n      <\/div>\n    <\/div>\n    \n    <div class=\"status-message\" id=\"status-message\"><\/div>\n  <\/div>\n<\/div>\n\n<script src=\"https:\/\/webapi.amap.com\/maps?v=2.0&#038;key=\u60a8\u7684\u9ad8\u5fb7\u5730\u56feAPI\u5bc6\u94a5\"><\/script>\n<script>\nconst TIMEE_LOCATION = {\n  name: \"TIMEE\uff09\",\n  lat: 31.8206,\n  lng: 117.2272\n};\n\n\/\/ DOM\u5143\u7d20\nconst getLocationBtn = document.getElementById('get-location-btn');\nconst resultEl = document.getElementById('result');\nconst distanceValueEl = document.getElementById('distance-value');\nconst distanceUnitEl = document.getElementById('distance-unit');\nconst userLocationEl = document.getElementById('user-location');\nconst statusMessageEl = document.getElementById('status-message');\n\n\/\/ \u8ba1\u7b97\u4e24\u4e2a\u5750\u6807\u4e4b\u95f4\u7684\u8ddd\u79bb\uff08Haversine\u516c\u5f0f\uff09\nfunction calculateDistance(lat1, lon1, lat2, lon2) {\n  const R = 6371; \/\/ \u5730\u7403\u534a\u5f84\uff0c\u5355\u4f4d\uff1a\u5343\u7c73\n  const dLat = (lat2 - lat1) * Math.PI \/ 180;\n  const dLon = (lon2 - lon1) * Math.PI \/ 180;\n  const a = \n    Math.sin(dLat\/2) * Math.sin(dLat\/2) +\n    Math.cos(lat1 * Math.PI \/ 180) * Math.cos(lat2 * Math.PI \/ 180) * \n    Math.sin(dLon\/2) * Math.sin(dLon\/2);\n  const c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1-a));\n  return R * c;\n}\n\n\/\/ \u663e\u793a\u72b6\u6001\u6d88\u606f\nfunction showStatus(message, type = 'info') {\n  statusMessageEl.textContent = message;\n  statusMessageEl.className = `status-message status-${type}`;\n  statusMessageEl.style.display = 'block';\n  \n  \/\/ 5\u79d2\u540e\u81ea\u52a8\u9690\u85cf\u4fe1\u606f\n  setTimeout(() => {\n    statusMessageEl.style.display = 'none';\n  }, 5000);\n}\n\n\/\/ \u66f4\u65b0\u8ddd\u79bb\u663e\u793a\nfunction updateDistance(distance) {\n  distanceValueEl.textContent = distance.toFixed(2);\n  distanceUnitEl.textContent = 'km';\n  resultEl.textContent = `\u60a8\u8ddd\u79bbTIMEE ${distance.toFixed(2)} km`;\n}\n\n\/\/ \u83b7\u53d6\u7528\u6237\u4f4d\u7f6e\nfunction getUserLocation() {\n  const btnIcon = document.querySelector('.btn-icon');\n  const btnText = document.querySelector('.btn-text');\n  \n  btnIcon.textContent = '\u23f3';\n  btnText.textContent = '\u5b9a\u4f4d\u4e2d...';\n  getLocationBtn.disabled = true;\n  \n  if (!navigator.geolocation) {\n    updateDistance(0);\n    showStatus('\u60a8\u7684\u6d4f\u89c8\u5668\u4e0d\u652f\u6301\u5730\u7406\u4f4d\u7f6e\u529f\u80fd', 'error');\n    btnIcon.textContent = '\ud83d\udccd';\n    btnText.textContent = '\u83b7\u53d6\u6211\u7684\u4f4d\u7f6e';\n    getLocationBtn.disabled = false;\n    return;\n  }\n  \n  navigator.geolocation.getCurrentPosition(\n    \/\/ \u6210\u529f\u56de\u8c03\n    (position) => {\n      const lat = position.coords.latitude;\n      const lng = position.coords.longitude;\n      const accuracy = position.coords.accuracy;\n      \n      \/\/ \u8ba1\u7b97\u8ddd\u79bb\n      const distance = calculateDistance(lat, lng, TIMEE_LOCATION.lat, TIMEE_LOCATION.lng);\n      \n      \/\/ \u66f4\u65b0\u663e\u793a\n      updateDistance(distance);\n      userLocationEl.textContent = `\u7eac\u5ea6: ${lat.toFixed(4)}, \u7ecf\u5ea6: ${lng.toFixed(4)}`;\n      \n      \/\/ \u6062\u590d\u6309\u94ae\u72b6\u6001\n      btnIcon.textContent = '\ud83d\udccd';\n      btnText.textContent = '\u91cd\u65b0\u83b7\u53d6\u4f4d\u7f6e';\n      getLocationBtn.disabled = false;\n      \n      \/\/ \u663e\u793a\u6210\u529f\u72b6\u6001\n      showStatus(`\u8ba1\u7b97\u6210\u529f\uff01`, 'success');\n    },\n    \/\/ \u9519\u8bef\u56de\u8c03\n    (error) => {\n      let errorMessage = '';\n      switch(error.code) {\n        case error.PERMISSION_DENIED:\n          errorMessage = '\u4f60\u62d2\u7edd\u4e86\u4f4d\u7f6e\u8bf7\u6c42\uff0c\u8bf7\u5141\u8bb8\u6d4f\u89c8\u5668\u8bbf\u95ee\u4f4d\u7f6e\u4fe1\u606f';\n          break;\n        case error.POSITION_UNAVAILABLE:\n          errorMessage = '\u4f4d\u7f6e\u4fe1\u606f\u4e0d\u53ef\u7528';\n          break;\n        case error.TIMEOUT:\n          errorMessage = '\u83b7\u53d6\u4f4d\u7f6e\u4fe1\u606f\u8d85\u65f6';\n          break;\n        default:\n          errorMessage = '\u53d1\u751f\u672a\u77e5\u9519\u8bef';\n      }\n      \n      \/\/ \u6062\u590d\u6309\u94ae\u72b6\u6001\n      btnIcon.textContent = '\ud83d\udccd';\n      btnText.textContent = '\u83b7\u53d6\u6211\u7684\u4f4d\u7f6e';\n      getLocationBtn.disabled = false;\n      \n      showStatus(`\u83b7\u53d6\u4f4d\u7f6e\u5931\u8d25: ${errorMessage}`, 'error');\n    },\n    \/\/ \u9009\u9879\n    {\n      enableHighAccuracy: true,\n      timeout: 10000,\n      maximumAge: 0\n    }\n  );\n}\n\n\/\/ \u4e8b\u4ef6\u76d1\u542c\ngetLocationBtn.addEventListener('click', getUserLocation);\n\n\/\/ \u6a21\u62df\u4f4d\u7f6e\u529f\u80fd\uff08\u7528\u4e8e\u6d4b\u8bd5\uff09\nfunction simulateLocation() {\n  \/\/ \u6a21\u62df\u5317\u4eac\u7684\u4f4d\u7f6e\n  const simulatedLat = 39.9042;\n  const simulatedLng = 116.4074;\n  \n  const distance = calculateDistance(simulatedLat, simulatedLng, TIMEE_LOCATION.lat, TIMEE_LOCATION.lng);\n  updateDistance(distance);\n  userLocationEl.textContent = `\u5317\u4eac (\u6a21\u62df\u4f4d\u7f6e)`;\n  showStatus('\u5df2\u4f7f\u7528\u6a21\u62df\u4f4d\u7f6e\u8fdb\u884c\u6d4b\u8bd5', 'info');\n}\n\n\/\/ \u4e3a\u4e86\u65b9\u4fbf\u6d4b\u8bd5\uff0c\u5728\u63a7\u5236\u53f0\u6dfb\u52a0\u6a21\u62df\u51fd\u6570\nwindow.simulateLocation = simulateLocation;\nconsole.log('\u6d4b\u8bd5\uff1a\u53ef\u4ee5\u5728\u63a7\u5236\u53f0\u4f7f\u7528simulateLocation()\u6a21\u62df\u5317\u4eac\u4f4d\u7f6e');\n<\/script>\n\n<style>\n#distance-module {\n  font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;\n  background: linear-gradient(135deg, #7CC2CB 0%, #5BA4AD 100%);\n  border-radius: 16px;\n  padding: 24px;\n  max-width: 400px;\n  margin: 0 auto;\n  color: white;\n  box-shadow: 0 10px 30px rgba(124, 194, 203, 0.3);\n  overflow: hidden;\n  position: relative;\n}\n\n#distance-module::before {\n  content: '';\n  position: absolute;\n  top: 0;\n  left: 0;\n  right: 0;\n  height: 4px;\n  background: linear-gradient(90deg, #7CC2CB 0%, #FFFFFF 50%, #7CC2CB 100%);\n}\n\n.distance-header {\n  text-align: center;\n  margin-bottom: 20px;\n}\n\n.distance-header h2 {\n  font-size: 24px;\n  font-weight: 700;\n  margin: 0 0 8px 0;\n  color: white;\n  text-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);\n}\n\n.distance-header .subtitle {\n  font-size: 14px;\n  opacity: 0.9;\n  margin: 0;\n  font-weight: 400;\n}\n\n.distance-body {\n  background: rgba(255, 255, 255, 0.95);\n  border-radius: 12px;\n  padding: 24px;\n  margin-bottom: 16px;\n  box-shadow: 0 4px 12px rgba(0, 0, 0, 0.05);\n}\n\n.location-btn {\n  background: linear-gradient(135deg, #7CC2CB 0%, #5BA4AD 100%);\n  color: white;\n  border: none;\n  padding: 14px 20px;\n  border-radius: 10px;\n  cursor: pointer;\n  font-size: 16px;\n  font-weight: 600;\n  width: 100%;\n  display: flex;\n  align-items: center;\n  justify-content: center;\n  gap: 10px;\n  margin-bottom: 24px;\n  transition: all 0.3s ease;\n  box-shadow: 0 4px 12px rgba(124, 194, 203, 0.3);\n}\n\n.location-btn:hover {\n  transform: translateY(-2px);\n  box-shadow: 0 6px 16px rgba(124, 194, 203, 0.4);\n}\n\n.location-btn:active {\n  transform: translateY(0);\n}\n\n.location-btn:disabled {\n  opacity: 0.7;\n  cursor: not-allowed;\n  transform: none !important;\n}\n\n.location-btn .btn-icon {\n  font-size: 20px;\n}\n\n.distance-result {\n  display: flex;\n  align-items: baseline;\n  justify-content: center;\n  margin-bottom: 8px;\n  padding: 10px;\n  background: linear-gradient(135deg, #f8fdff 0%, #e8f7fa 100%);\n  border-radius: 10px;\n  border: 2px solid #e1f5f9;\n}\n\n.distance-value {\n  font-size: 48px;\n  font-weight: 800;\n  color: #2C6A73;\n  line-height: 1;\n}\n\n.distance-unit {\n  font-size: 20px;\n  font-weight: 600;\n  color: #5BA4AD;\n  margin-left: 4px;\n}\n\n.distance-label {\n  text-align: center;\n  font-size: 16px;\n  color: #4a6b71;\n  margin-bottom: 20px;\n  font-weight: 500;\n}\n\n.location-info {\n  background: #f8fdff;\n  border-radius: 8px;\n  padding: 16px;\n  margin-top: 16px;\n  border: 1px solid #e1f5f9;\n}\n\n.info-item {\n  display: flex;\n  margin-bottom: 10px;\n  padding-bottom: 10px;\n  border-bottom: 1px dashed #e1f5f9;\n}\n\n.info-item:last-child {\n  margin-bottom: 0;\n  padding-bottom: 0;\n  border-bottom: none;\n}\n\n.info-label {\n  font-weight: 600;\n  color: #5BA4AD;\n  min-width: 90px;\n  font-size: 14px;\n}\n\n.info-value {\n  color: #4a6b71;\n  font-size: 14px;\n  flex: 1;\n}\n\n.status-message {\n  display: none;\n  padding: 12px;\n  border-radius: 8px;\n  margin-top: 16px;\n  font-size: 14px;\n  text-align: center;\n}\n\n.status-success {\n  background-color: #e7f7ef;\n  color: #0a7c42;\n  border: 1px solid #a3e9c4;\n}\n\n.status-error {\n  background-color: #fde8e8;\n  color: #c53030;\n  border: 1px solid #feb2b2;\n}\n\n.status-info {\n  background-color: #e1effe;\n  color: #2C6A73;\n  border: 1px solid #a4cafe;\n}\n\n.distance-footer {\n  text-align: center;\n}\n\n.distance-footer .hint {\n  font-size: 12px;\n  opacity: 0.8;\n  margin: 0;\n  font-style: italic;\n}\n\n\/* \u54cd\u5e94\u5f0f\u8c03\u6574 *\/\n@media (max-width: 480px) {\n  #distance-module {\n    padding: 16px;\n    max-width: 100%;\n  }\n  \n  .distance-body {\n    padding: 16px;\n  }\n  \n  .distance-value {\n    font-size: 40px;\n  }\n}\n<\/style>\n","protected":false},"excerpt":{"rendered":"<p>\u60f3\u77e5\u9053\u73b0\u5728\u548c\u949b\u5f25\u4e4b\u95f4\u7684\u76f4\u7ebf\u8ddd\u79bb\u6709\u591a\u8fdc\u5417\uff1f\u70b9\u51fb\u83b7\u53d6\u4f4d\u7f6e\u6309\u94ae\u770b\u770b [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_EventAllDay":false,"_EventTimezone":"","_EventStartDate":"","_EventEndDate":"","_EventStartDateUTC":"","_EventEndDateUTC":"","_EventShowMap":false,"_EventShowMapLink":false,"_EventURL":"","_EventCost":"","_EventCostDescription":"","_EventCurrencySymbol":"","_EventCurrencyCode":"","_EventCurrencyPosition":"","_EventDateTimeSeparator":"","_EventTimeRangeSeparator":"","_EventOrganizerID":[],"_EventVenueID":[],"_OrganizerEmail":"","_OrganizerPhone":"","_OrganizerWebsite":"","_VenueAddress":"","_VenueCity":"","_VenueCountry":"","_VenueProvince":"","_VenueState":"","_VenueZip":"","_VenuePhone":"","_VenueURL":"","_VenueStateProvince":"","_VenueLat":"","_VenueLng":"","_VenueShowMap":false,"_VenueShowMapLink":false,"_jetpack_memberships_contains_paid_content":false,"footnotes":""},"categories":[16],"tags":[],"class_list":["post-371","post","type-post","status-publish","format-standard","hentry","category-16"],"jetpack_featured_media_url":"","jetpack_sharing_enabled":true,"_links":{"self":[{"href":"https:\/\/timee.love\/index.php?rest_route=\/wp\/v2\/posts\/371","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/timee.love\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/timee.love\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/timee.love\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/timee.love\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=371"}],"version-history":[{"count":13,"href":"https:\/\/timee.love\/index.php?rest_route=\/wp\/v2\/posts\/371\/revisions"}],"predecessor-version":[{"id":384,"href":"https:\/\/timee.love\/index.php?rest_route=\/wp\/v2\/posts\/371\/revisions\/384"}],"wp:attachment":[{"href":"https:\/\/timee.love\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=371"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/timee.love\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=371"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/timee.love\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=371"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}