plan-detail.js 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362
  1. "use strict";
  2. const common_vendor = require("../../common/vendor.js");
  3. const _sfc_main = {
  4. data() {
  5. return {
  6. selectedLocations: [],
  7. tripDays: 1,
  8. budget: "",
  9. startDate: (/* @__PURE__ */ new Date()).toISOString().split("T")[0],
  10. // 今天的日期,格式:YYYY-MM-DD
  11. peopleCount: 2,
  12. options: {},
  13. editMode: false,
  14. tripId: null
  15. };
  16. },
  17. computed: {
  18. // 计算推荐天数
  19. recommendedDays() {
  20. return Math.max(1, Math.ceil(this.selectedLocations.length / 3));
  21. },
  22. // 检查是否可以提交
  23. canSubmit() {
  24. return this.selectedLocations.length > 0 && this.tripDays >= 1 && this.budget && this.startDate;
  25. }
  26. },
  27. onLoad(options) {
  28. common_vendor.index.__f__("log", "at pages/custom-trip/plan-detail.vue:124", "规划详情页参数:", options);
  29. this.options = options || {};
  30. this.editMode = options && options.tripId ? true : false;
  31. this.tripId = options && options.tripId ? options.tripId : null;
  32. try {
  33. const locationsData = common_vendor.index.getStorageSync("selectedLocations");
  34. if (locationsData) {
  35. this.selectedLocations = JSON.parse(locationsData);
  36. common_vendor.index.__f__("log", "at pages/custom-trip/plan-detail.vue:134", "已加载选择的景点数据:", this.selectedLocations);
  37. if (this.editMode && this.tripId) {
  38. this.loadExistingTripData();
  39. } else {
  40. this.tripDays = this.recommendedDays;
  41. }
  42. } else {
  43. common_vendor.index.__f__("log", "at pages/custom-trip/plan-detail.vue:144", "未找到已选景点数据");
  44. common_vendor.index.showToast({
  45. title: "请先选择景点",
  46. icon: "none"
  47. });
  48. setTimeout(() => {
  49. common_vendor.index.navigateBack();
  50. }, 1500);
  51. }
  52. } catch (e) {
  53. common_vendor.index.__f__("error", "at pages/custom-trip/plan-detail.vue:155", "读取已选景点数据失败:", e);
  54. }
  55. },
  56. methods: {
  57. // 加载现有行程数据
  58. loadExistingTripData() {
  59. try {
  60. const savedTrips = common_vendor.index.getStorageSync("savedTrips") || [];
  61. const tripData = savedTrips.find((trip) => trip.id === this.tripId);
  62. if (tripData) {
  63. common_vendor.index.__f__("log", "at pages/custom-trip/plan-detail.vue:168", "找到现有行程数据:", tripData);
  64. this.tripDays = tripData.days || 1;
  65. this.budget = tripData.budget ? tripData.budget.toString() : "";
  66. this.startDate = tripData.startDate;
  67. this.peopleCount = tripData.peopleCount || 2;
  68. common_vendor.index.setNavigationBarTitle({
  69. title: "修改行程"
  70. });
  71. } else {
  72. common_vendor.index.__f__("log", "at pages/custom-trip/plan-detail.vue:180", "未找到现有行程数据");
  73. this.tripDays = this.recommendedDays;
  74. }
  75. } catch (e) {
  76. common_vendor.index.__f__("error", "at pages/custom-trip/plan-detail.vue:184", "加载现有行程数据失败:", e);
  77. this.tripDays = this.recommendedDays;
  78. }
  79. },
  80. // 增加天数
  81. increaseDays() {
  82. this.tripDays++;
  83. },
  84. // 减少天数
  85. decreaseDays() {
  86. if (this.tripDays > 1) {
  87. this.tripDays--;
  88. }
  89. },
  90. // 增加人数
  91. increasePeople() {
  92. this.peopleCount++;
  93. },
  94. // 减少人数
  95. decreasePeople() {
  96. if (this.peopleCount > 1) {
  97. this.peopleCount--;
  98. }
  99. },
  100. // 格式化日期显示
  101. formatDate(dateString) {
  102. if (!dateString)
  103. return "请选择日期";
  104. const date = new Date(dateString);
  105. return `${date.getFullYear()}.${date.getMonth() + 1}.${date.getDate()}`;
  106. },
  107. // 日期选择变化处理
  108. onDateChange(e) {
  109. this.startDate = e.detail.value;
  110. },
  111. // 移除景点
  112. removeSpot(index) {
  113. common_vendor.index.showModal({
  114. title: "移除景点",
  115. content: `确定要移除"${this.selectedLocations[index].name}"吗?`,
  116. success: (res) => {
  117. if (res.confirm) {
  118. this.selectedLocations.splice(index, 1);
  119. this.updateLocalStorage();
  120. }
  121. }
  122. });
  123. },
  124. // 更新本地存储
  125. updateLocalStorage() {
  126. try {
  127. common_vendor.index.setStorageSync("selectedLocations", JSON.stringify(this.selectedLocations));
  128. common_vendor.index.__f__("log", "at pages/custom-trip/plan-detail.vue:244", "已更新本地存储的景点数据");
  129. } catch (e) {
  130. common_vendor.index.__f__("error", "at pages/custom-trip/plan-detail.vue:246", "更新本地存储失败:", e);
  131. }
  132. },
  133. // 创建行程
  134. createTrip() {
  135. if (!this.canSubmit) {
  136. common_vendor.index.showToast({
  137. title: "请完善行程信息",
  138. icon: "none"
  139. });
  140. return;
  141. }
  142. common_vendor.index.showLoading({
  143. title: this.editMode ? "保存更改中..." : "行程生成中..."
  144. });
  145. const spotsWithCoverImage = this.selectedLocations.map((location, index) => {
  146. let coverImage = "/static/baoding.jpg";
  147. if (location.name && location.name.includes("古莲花池")) {
  148. coverImage = "/static/baoding.jpg";
  149. } else if (location.name && location.name.includes("直隶")) {
  150. coverImage = "/static/xian.jpg";
  151. } else if (location.name && location.name.includes("野三坡")) {
  152. coverImage = "/static/beijing.jpg";
  153. } else {
  154. const images = [
  155. "/static/baoding.jpg",
  156. "/static/beijing.jpg",
  157. "/static/shanghai.jpg",
  158. "/static/chengdu.jpg"
  159. ];
  160. const imageIndex = index % images.length;
  161. coverImage = images[imageIndex];
  162. }
  163. let distanceFromPrevious = null;
  164. if (index > 0) {
  165. const prevLocation = this.selectedLocations[index - 1];
  166. distanceFromPrevious = this.calculateDistance(
  167. prevLocation.latitude,
  168. prevLocation.longitude,
  169. location.latitude,
  170. location.longitude
  171. );
  172. }
  173. const latitude = Number(location.latitude);
  174. const longitude = Number(location.longitude);
  175. common_vendor.index.__f__("log", "at pages/custom-trip/plan-detail.vue:304", `景点${index + 1} - ${location.name} 经纬度:`, latitude, longitude);
  176. return {
  177. id: location.id || `spot_${Date.now()}_${index}`,
  178. // 确保有唯一ID
  179. name: location.name || "未命名景点",
  180. address: location.address || "无地址信息",
  181. latitude,
  182. longitude,
  183. order: index + 1,
  184. coverImage,
  185. // 添加封面图片
  186. distanceFromPrevious
  187. // 添加距离信息
  188. };
  189. });
  190. const tripData = {
  191. name: "保定自定义行程",
  192. days: this.tripDays,
  193. budget: this.budget ? Number(this.budget) : null,
  194. startDate: this.startDate,
  195. peopleCount: this.peopleCount,
  196. spots: spotsWithCoverImage,
  197. createdAt: (/* @__PURE__ */ new Date()).toISOString(),
  198. updatedAt: (/* @__PURE__ */ new Date()).toISOString()
  199. };
  200. if (this.editMode && this.tripId) {
  201. if (this.tripId.startsWith("trip_")) {
  202. tripData.id = null;
  203. } else {
  204. tripData.id = this.tripId;
  205. }
  206. } else {
  207. tripData.id = null;
  208. }
  209. common_vendor.index.__f__("log", "at pages/custom-trip/plan-detail.vue:344", "准备保存行程数据:", JSON.stringify(tripData));
  210. if (this.$api && this.$api.trip) {
  211. const apiMethod = this.editMode ? this.$api.trip.update : this.$api.trip.create;
  212. apiMethod(tripData).then((res) => {
  213. common_vendor.index.__f__("log", "at pages/custom-trip/plan-detail.vue:353", "API保存行程成功:", res);
  214. const finalTripData = res && res.data ? res.data : tripData;
  215. this.saveToLocalStorage(finalTripData, true);
  216. common_vendor.index.removeStorageSync("selectedLocations");
  217. common_vendor.index.showToast({
  218. title: this.editMode ? "行程更新成功!" : "行程创建成功!",
  219. icon: "success",
  220. duration: 2e3
  221. });
  222. setTimeout(() => {
  223. common_vendor.index.switchTab({
  224. url: "/pages/planning/index",
  225. success: () => {
  226. common_vendor.index.$emit("refreshTrips");
  227. common_vendor.index.__f__("log", "at pages/custom-trip/plan-detail.vue:377", "成功返回规划页面并请求刷新");
  228. }
  229. });
  230. }, 1e3);
  231. }).catch((err) => {
  232. common_vendor.index.__f__("error", "at pages/custom-trip/plan-detail.vue:383", "API请求失败,回退到本地存储:", err);
  233. this.saveToLocalStorage(tripData);
  234. }).finally(() => {
  235. common_vendor.index.hideLoading();
  236. });
  237. } else {
  238. common_vendor.index.__f__("log", "at pages/custom-trip/plan-detail.vue:392", "API不可用,使用本地存储保存行程");
  239. this.saveToLocalStorage(tripData);
  240. }
  241. },
  242. // 保存到本地存储(作为后备方案)
  243. saveToLocalStorage(tripData, skipToast = false) {
  244. try {
  245. let savedTrips = common_vendor.index.getStorageSync("savedTrips") || [];
  246. if (this.editMode && this.tripId) {
  247. const index = savedTrips.findIndex((trip) => trip.id === this.tripId);
  248. if (index !== -1) {
  249. const originalCreatedAt = savedTrips[index].createdAt;
  250. tripData.createdAt = originalCreatedAt;
  251. savedTrips[index] = tripData;
  252. if (!skipToast) {
  253. common_vendor.index.showToast({
  254. title: "行程更新成功!",
  255. icon: "success",
  256. duration: 2e3
  257. });
  258. }
  259. }
  260. } else {
  261. savedTrips.push(tripData);
  262. if (!skipToast) {
  263. common_vendor.index.showToast({
  264. title: "行程创建成功!",
  265. icon: "success",
  266. duration: 2e3
  267. });
  268. }
  269. }
  270. common_vendor.index.__f__("log", "at pages/custom-trip/plan-detail.vue:435", "保存到本地的行程数据:", savedTrips);
  271. common_vendor.index.setStorageSync("savedTrips", savedTrips);
  272. common_vendor.index.removeStorageSync("selectedLocations");
  273. if (!skipToast) {
  274. setTimeout(() => {
  275. common_vendor.index.switchTab({
  276. url: "/pages/planning/index",
  277. success: () => {
  278. common_vendor.index.$emit("refreshTrips");
  279. common_vendor.index.__f__("log", "at pages/custom-trip/plan-detail.vue:452", "成功返回规划页面并请求刷新");
  280. },
  281. fail: (err) => {
  282. common_vendor.index.__f__("error", "at pages/custom-trip/plan-detail.vue:455", "返回规划页面失败:", err);
  283. }
  284. });
  285. }, 1e3);
  286. }
  287. } catch (e) {
  288. common_vendor.index.__f__("error", "at pages/custom-trip/plan-detail.vue:461", "保存行程失败:", e);
  289. common_vendor.index.showToast({
  290. title: "保存行程失败",
  291. icon: "none"
  292. });
  293. }
  294. },
  295. // 返回上一页
  296. goBack() {
  297. common_vendor.index.navigateBack();
  298. },
  299. // 计算两点之间的距离(公里)
  300. calculateDistance(lat1, lng1, lat2, lng2) {
  301. lat1 = Number(lat1);
  302. lng1 = Number(lng1);
  303. lat2 = Number(lat2);
  304. lng2 = Number(lng2);
  305. if (isNaN(lat1) || isNaN(lng1) || isNaN(lat2) || isNaN(lng2)) {
  306. return null;
  307. }
  308. const R = 6371;
  309. const dLat = this.toRadians(lat2 - lat1);
  310. const dLng = this.toRadians(lng2 - lng1);
  311. const a = Math.sin(dLat / 2) * Math.sin(dLat / 2) + Math.cos(this.toRadians(lat1)) * Math.cos(this.toRadians(lat2)) * Math.sin(dLng / 2) * Math.sin(dLng / 2);
  312. const c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a));
  313. const distance = R * c;
  314. return parseFloat(distance.toFixed(1));
  315. },
  316. // 角度转弧度
  317. toRadians(degrees) {
  318. return degrees * Math.PI / 180;
  319. }
  320. }
  321. };
  322. function _sfc_render(_ctx, _cache, $props, $setup, $data, $options) {
  323. return common_vendor.e({
  324. a: common_vendor.o((...args) => $options.goBack && $options.goBack(...args)),
  325. b: common_vendor.t($data.editMode ? "修改行程" : "定制行程"),
  326. c: common_vendor.t($data.selectedLocations.length),
  327. d: common_vendor.t($data.editMode ? "请修改行程信息" : "请完善行程信息"),
  328. e: common_vendor.o((...args) => $options.decreaseDays && $options.decreaseDays(...args)),
  329. f: $data.tripDays <= 1 ? 1 : "",
  330. g: common_vendor.t($data.tripDays),
  331. h: common_vendor.o((...args) => $options.increaseDays && $options.increaseDays(...args)),
  332. i: common_vendor.t($options.recommendedDays),
  333. j: $data.budget,
  334. k: common_vendor.o(($event) => $data.budget = $event.detail.value),
  335. l: common_vendor.t($options.formatDate($data.startDate)),
  336. m: $data.startDate,
  337. n: common_vendor.o((...args) => $options.onDateChange && $options.onDateChange(...args)),
  338. o: common_vendor.o((...args) => $options.decreasePeople && $options.decreasePeople(...args)),
  339. p: $data.peopleCount <= 1 ? 1 : "",
  340. q: common_vendor.t($data.peopleCount),
  341. r: common_vendor.o((...args) => $options.increasePeople && $options.increasePeople(...args)),
  342. s: common_vendor.f($data.selectedLocations, (spot, index, i0) => {
  343. return {
  344. a: common_vendor.t(index + 1),
  345. b: common_vendor.t(spot.name || "未命名景点"),
  346. c: common_vendor.t(spot.address || "无地址信息"),
  347. d: common_vendor.o(($event) => $options.removeSpot(index), index),
  348. e: index
  349. };
  350. }),
  351. t: $data.selectedLocations.length === 0
  352. }, $data.selectedLocations.length === 0 ? {} : {}, {
  353. v: common_vendor.t($data.editMode ? "" : "修改"),
  354. w: common_vendor.o((...args) => $options.goBack && $options.goBack(...args)),
  355. x: common_vendor.t($data.editMode ? "保存修改" : "生成行程"),
  356. y: common_vendor.o((...args) => $options.createTrip && $options.createTrip(...args)),
  357. z: !$options.canSubmit ? 1 : ""
  358. });
  359. }
  360. const MiniProgramPage = /* @__PURE__ */ common_vendor._export_sfc(_sfc_main, [["render", _sfc_render]]);
  361. wx.createPage(MiniProgramPage);
  362. //# sourceMappingURL=../../../.sourcemap/mp-weixin/pages/custom-trip/plan-detail.js.map