index.js 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570
  1. "use strict";
  2. const common_vendor = require("../../common/vendor.js");
  3. const util_api = require("../../util/api.js");
  4. const _sfc_main = {
  5. data() {
  6. return {
  7. isLoading: false,
  8. tripId: null,
  9. tripData: {},
  10. options: null,
  11. defaultImages: [
  12. "/static/baoding.jpg",
  13. "/static/custom_plan_icon.png",
  14. "/static/beijing.jpg",
  15. "/static/chengdu.jpg"
  16. ],
  17. showQrCode: false,
  18. qrCodeUrl: "",
  19. qrCodeExpireTime: 0
  20. };
  21. },
  22. onLoad(options) {
  23. common_vendor.index.__f__("log", "at pages/travel-detail/index.vue:136", "行程详情页面加载,参数:", options);
  24. this.options = options;
  25. if (options && options.planId) {
  26. common_vendor.index.__f__("log", "at pages/travel-detail/index.vue:141", "接收到行程ID:", options.planId);
  27. this.tripId = options.planId;
  28. this.loadTripData();
  29. } else {
  30. common_vendor.index.__f__("log", "at pages/travel-detail/index.vue:145", "没有接收到行程ID,使用默认数据");
  31. this.createDefaultTrip();
  32. }
  33. },
  34. // 监听app全局事件
  35. onShow() {
  36. common_vendor.index.$on("loadTripDetail", this.handleLoadTripDetail);
  37. },
  38. onHide() {
  39. common_vendor.index.$off("loadTripDetail", this.handleLoadTripDetail);
  40. },
  41. methods: {
  42. // 处理通过事件加载行程
  43. handleLoadTripDetail(data) {
  44. if (data && data.tripId) {
  45. common_vendor.index.__f__("log", "at pages/travel-detail/index.vue:166", "通过事件加载行程:", data.tripId);
  46. this.tripId = data.tripId;
  47. this.loadTripData();
  48. }
  49. },
  50. // 创建默认行程
  51. createDefaultTrip() {
  52. this.tripData = {
  53. id: "default_trip_" + Date.now(),
  54. name: "保定精彩三日游",
  55. days: 3,
  56. nights: 2,
  57. startDate: this.formatDate(/* @__PURE__ */ new Date()),
  58. budget: 1580
  59. };
  60. common_vendor.index.showToast({
  61. title: "默认行程已生成",
  62. icon: "success"
  63. });
  64. },
  65. // 加载行程数据
  66. loadTripData() {
  67. this.isLoading = true;
  68. if (this.tripId && !this.tripId.startsWith("trip_")) {
  69. util_api.API.trip.detail(this.tripId).then((res) => {
  70. if (res.data) {
  71. this.tripData = res.data;
  72. common_vendor.index.showToast({
  73. title: "行程加载成功",
  74. icon: "success"
  75. });
  76. } else {
  77. common_vendor.index.__f__("log", "at pages/travel-detail/index.vue:206", "API返回空数据,尝试从本地加载");
  78. this.loadFromLocalStorage();
  79. }
  80. }).catch((err) => {
  81. common_vendor.index.__f__("error", "at pages/travel-detail/index.vue:211", "通过API加载行程失败:", err);
  82. this.loadFromLocalStorage();
  83. }).finally(() => {
  84. this.isLoading = false;
  85. });
  86. } else {
  87. this.loadFromLocalStorage();
  88. }
  89. },
  90. // 从本地存储加载行程
  91. loadFromLocalStorage() {
  92. try {
  93. const savedTrips = common_vendor.index.getStorageSync("savedTrips") || [];
  94. common_vendor.index.__f__("log", "at pages/travel-detail/index.vue:228", "已保存行程:", savedTrips);
  95. const tripData = savedTrips.find((trip) => trip.id === this.tripId);
  96. if (tripData) {
  97. common_vendor.index.__f__("log", "at pages/travel-detail/index.vue:234", "找到行程数据:", tripData);
  98. this.tripData = tripData;
  99. common_vendor.index.showToast({
  100. title: "行程加载成功",
  101. icon: "success"
  102. });
  103. } else {
  104. common_vendor.index.__f__("log", "at pages/travel-detail/index.vue:242", "未找到行程数据,使用默认数据");
  105. this.createDefaultTrip();
  106. }
  107. } catch (e) {
  108. common_vendor.index.__f__("error", "at pages/travel-detail/index.vue:247", "加载行程数据失败:", e);
  109. this.createDefaultTrip();
  110. } finally {
  111. this.isLoading = false;
  112. }
  113. },
  114. // 修改行程
  115. editTrip() {
  116. if (!this.tripData || !this.tripData.id) {
  117. common_vendor.index.showToast({
  118. title: "无法修改默认行程",
  119. icon: "none"
  120. });
  121. return;
  122. }
  123. try {
  124. if (this.tripData.spots && this.tripData.spots.length > 0) {
  125. common_vendor.index.setStorageSync("selectedLocations", JSON.stringify(this.tripData.spots));
  126. common_vendor.index.navigateTo({
  127. url: `/pages/custom-trip/plan-detail?tripId=${this.tripData.id}`,
  128. success: () => {
  129. common_vendor.index.__f__("log", "at pages/travel-detail/index.vue:275", "成功跳转到行程编辑页面,行程ID:", this.tripData.id);
  130. },
  131. fail: (err) => {
  132. common_vendor.index.__f__("error", "at pages/travel-detail/index.vue:278", "跳转到行程编辑页面失败:", err);
  133. common_vendor.index.showToast({
  134. title: "跳转失败",
  135. icon: "none"
  136. });
  137. }
  138. });
  139. } else {
  140. common_vendor.index.showToast({
  141. title: "行程没有景点数据",
  142. icon: "none"
  143. });
  144. }
  145. } catch (e) {
  146. common_vendor.index.__f__("error", "at pages/travel-detail/index.vue:292", "保存临时数据失败:", e);
  147. common_vendor.index.showToast({
  148. title: "准备编辑数据失败",
  149. icon: "none"
  150. });
  151. }
  152. },
  153. // 获取行程封面图片
  154. getTripCoverImage() {
  155. if (this.tripData.spots && this.tripData.spots.length > 0) {
  156. if (this.tripData.spots[0].coverImage) {
  157. return this.tripData.spots[0].coverImage;
  158. }
  159. }
  160. if (this.tripData.name && this.tripData.name.includes("保定")) {
  161. return "/static/baoding.jpg";
  162. } else if (this.tripData.name && this.tripData.name.includes("西安")) {
  163. return "/static/xian.jpg";
  164. } else if (this.tripData.name && this.tripData.name.includes("北京")) {
  165. return "/static/beijing.jpg";
  166. } else if (this.tripData.name && this.tripData.name.includes("上海")) {
  167. return "/static/shanghai.jpg";
  168. }
  169. const hash = this.tripData.id ? this.tripData.id.split("_")[1] : Date.now();
  170. const index = hash % this.defaultImages.length;
  171. return this.defaultImages[index];
  172. },
  173. // 格式化日期
  174. formatDate(date) {
  175. if (!date) {
  176. const now = /* @__PURE__ */ new Date();
  177. const year = now.getFullYear();
  178. const month = now.getMonth() + 1;
  179. const day = now.getDate();
  180. return `${year}.${month}.${day}`;
  181. }
  182. if (date instanceof Date) {
  183. const year = date.getFullYear();
  184. const month = date.getMonth() + 1;
  185. const day = date.getDate();
  186. return `${year}.${month}.${day}`;
  187. }
  188. return date;
  189. },
  190. // 返回上一页
  191. goBack() {
  192. common_vendor.index.navigateBack({
  193. fail: () => {
  194. this.goToHome();
  195. }
  196. });
  197. },
  198. // 回到首页
  199. goToHome() {
  200. common_vendor.index.switchTab({
  201. url: "/pages/planning/index"
  202. });
  203. },
  204. // 计算两个景点之间的距离
  205. calculateDistance(spot1, spot2) {
  206. if (!spot1 || !spot2 || !spot1.latitude || !spot1.longitude || !spot2.latitude || !spot2.longitude) {
  207. return "未知";
  208. }
  209. const lat1 = Number(spot1.latitude);
  210. const lng1 = Number(spot1.longitude);
  211. const lat2 = Number(spot2.latitude);
  212. const lng2 = Number(spot2.longitude);
  213. if (isNaN(lat1) || isNaN(lng1) || isNaN(lat2) || isNaN(lng2)) {
  214. return "未知";
  215. }
  216. const R = 6371;
  217. const dLat = this.toRadians(lat2 - lat1);
  218. const dLng = this.toRadians(lng2 - lng1);
  219. 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);
  220. const c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a));
  221. const distance = R * c;
  222. return distance.toFixed(1);
  223. },
  224. // 角度转弧度
  225. toRadians(degrees) {
  226. return degrees * Math.PI / 180;
  227. },
  228. // 获取两个景点之间的距离
  229. getDistanceBetween(spot1, spot2) {
  230. if (spot2.distanceFromPrevious !== void 0 && spot2.distanceFromPrevious !== null) {
  231. return spot2.distanceFromPrevious;
  232. }
  233. return this.calculateDistance(spot1, spot2);
  234. },
  235. // 显示删除确认对话框
  236. showDeleteConfirm() {
  237. if (!this.tripData || !this.tripData.id) {
  238. common_vendor.index.showToast({
  239. title: "无法删除默认行程",
  240. icon: "none"
  241. });
  242. return;
  243. }
  244. common_vendor.index.showModal({
  245. title: "确认删除",
  246. content: "确定要删除此行程吗?此操作不可恢复。",
  247. confirmColor: "#ff4d4f",
  248. success: (res) => {
  249. if (res.confirm) {
  250. this.deleteTrip();
  251. }
  252. }
  253. });
  254. },
  255. // 删除行程
  256. deleteTrip() {
  257. common_vendor.index.showLoading({
  258. title: "正在删除...",
  259. mask: true
  260. });
  261. if (this.tripId && !this.tripId.startsWith("trip_")) {
  262. util_api.API.trip.delete(this.tripId).then((res) => {
  263. common_vendor.index.__f__("log", "at pages/travel-detail/index.vue:449", "API删除行程成功:", res);
  264. this.deleteFromLocalStorage();
  265. common_vendor.index.showToast({
  266. title: "行程已删除",
  267. icon: "success"
  268. });
  269. setTimeout(() => {
  270. this.goToHome();
  271. }, 1e3);
  272. }).catch((err) => {
  273. common_vendor.index.__f__("error", "at pages/travel-detail/index.vue:464", "通过API删除行程失败:", err);
  274. this.deleteFromLocalStorage();
  275. }).finally(() => {
  276. common_vendor.index.hideLoading();
  277. });
  278. } else {
  279. this.deleteFromLocalStorage();
  280. common_vendor.index.hideLoading();
  281. }
  282. },
  283. // 从本地存储中删除行程
  284. deleteFromLocalStorage() {
  285. try {
  286. const savedTrips = common_vendor.index.getStorageSync("savedTrips") || [];
  287. const updatedTrips = savedTrips.filter((trip) => trip.id !== this.tripId);
  288. common_vendor.index.setStorageSync("savedTrips", updatedTrips);
  289. common_vendor.index.showToast({
  290. title: "行程已删除",
  291. icon: "success"
  292. });
  293. common_vendor.index.$emit("refreshTrips");
  294. setTimeout(() => {
  295. this.goToHome();
  296. }, 1e3);
  297. } catch (e) {
  298. common_vendor.index.__f__("error", "at pages/travel-detail/index.vue:503", "从本地存储删除行程失败:", e);
  299. common_vendor.index.showToast({
  300. title: "删除失败",
  301. icon: "none"
  302. });
  303. }
  304. },
  305. // 处理弹窗背景点击
  306. handlePopupBackdrop(e) {
  307. this.closeQrCode();
  308. },
  309. // 分享行程方法
  310. shareTrip() {
  311. common_vendor.index.__f__("log", "at pages/travel-detail/index.vue:519", "点击分享按钮");
  312. this.generateQrCode();
  313. common_vendor.index.showToast({
  314. title: "正在生成二维码",
  315. icon: "loading",
  316. duration: 1e3
  317. });
  318. },
  319. // 生成行程二维码
  320. generateQrCode() {
  321. common_vendor.index.__f__("log", "at pages/travel-detail/index.vue:533", "点击生成二维码按钮");
  322. if (!this.tripData || !this.tripData.id) {
  323. common_vendor.index.showToast({
  324. title: "无法生成默认行程的二维码",
  325. icon: "none"
  326. });
  327. return;
  328. }
  329. if (this.qrCodeUrl && this.qrCodeExpireTime > Date.now()) {
  330. common_vendor.index.__f__("log", "at pages/travel-detail/index.vue:544", "使用缓存的二维码");
  331. this.showQrCode = true;
  332. return;
  333. }
  334. this.generateLocalQrCode();
  335. const simpleTripData = {
  336. id: this.tripData.id,
  337. name: this.tripData.name,
  338. days: this.tripData.days,
  339. budget: this.tripData.budget
  340. };
  341. common_vendor.index.__f__("log", "at pages/travel-detail/index.vue:561", "发送到后端的数据:", JSON.stringify(simpleTripData));
  342. util_api.API.trip.generateQrCode(simpleTripData).then((res) => {
  343. var _a, _b, _c;
  344. common_vendor.index.__f__("log", "at pages/travel-detail/index.vue:567", "后端返回的二维码数据:", res);
  345. if (res.qrCodeUrl || ((_a = res.data) == null ? void 0 : _a.qrCodeUrl)) {
  346. this.qrCodeUrl = res.qrCodeUrl || ((_b = res.data) == null ? void 0 : _b.qrCodeUrl);
  347. this.qrCodeExpireTime = res.expireTime || ((_c = res.data) == null ? void 0 : _c.expireTime) || Date.now() + 36e5;
  348. common_vendor.index.__f__("log", "at pages/travel-detail/index.vue:575", "二维码URL:", this.qrCodeUrl);
  349. common_vendor.index.__f__("log", "at pages/travel-detail/index.vue:576", "二维码内容:", res.qrContent || "未提供");
  350. this.$nextTick(() => {
  351. common_vendor.index.__f__("log", "at pages/travel-detail/index.vue:581", "二维码图片已更新");
  352. common_vendor.index.showToast({
  353. title: "二维码生成成功",
  354. icon: "success",
  355. duration: 1500
  356. });
  357. });
  358. } else {
  359. common_vendor.index.__f__("error", "at pages/travel-detail/index.vue:591", "生成二维码失败: 返回数据中无qrCodeUrl", res);
  360. common_vendor.index.showToast({
  361. title: "使用本地二维码",
  362. icon: "none"
  363. });
  364. }
  365. }).catch((err) => {
  366. common_vendor.index.__f__("error", "at pages/travel-detail/index.vue:600", "生成二维码失败:", err);
  367. common_vendor.index.showToast({
  368. title: "使用本地二维码",
  369. icon: "none",
  370. duration: 1500
  371. });
  372. });
  373. },
  374. // 生成本地二维码(不依赖后端)
  375. generateLocalQrCode() {
  376. try {
  377. this.showQrCode = true;
  378. const qrContent = `pages/travel-detail/index?planId=${this.tripData.id}`;
  379. const loadingQrCode = `https://api.qrserver.com/v1/create-qr-code/?size=200x200&data=${encodeURIComponent(qrContent)}`;
  380. this.qrCodeUrl = loadingQrCode;
  381. common_vendor.index.__f__("log", "at pages/travel-detail/index.vue:620", "生成临时二维码:", loadingQrCode);
  382. common_vendor.index.__f__("log", "at pages/travel-detail/index.vue:621", "二维码内容:", qrContent);
  383. } catch (e) {
  384. common_vendor.index.__f__("error", "at pages/travel-detail/index.vue:625", "生成本地二维码失败:", e);
  385. }
  386. },
  387. // 关闭二维码弹窗
  388. closeQrCode() {
  389. this.showQrCode = false;
  390. },
  391. // 保存二维码到相册
  392. saveQrCode() {
  393. if (!this.qrCodeUrl) {
  394. common_vendor.index.showToast({
  395. title: "二维码不存在",
  396. icon: "none"
  397. });
  398. return;
  399. }
  400. common_vendor.index.getSetting({
  401. success: (res) => {
  402. if (!res.authSetting["scope.writePhotosAlbum"]) {
  403. common_vendor.index.authorize({
  404. scope: "scope.writePhotosAlbum",
  405. success: () => {
  406. this.downloadQrCode();
  407. },
  408. fail: () => {
  409. common_vendor.index.showModal({
  410. title: "提示",
  411. content: "请授权保存图片到相册的权限",
  412. confirmText: "去设置",
  413. success: (res2) => {
  414. if (res2.confirm) {
  415. common_vendor.index.openSetting();
  416. }
  417. }
  418. });
  419. }
  420. });
  421. } else {
  422. this.downloadQrCode();
  423. }
  424. }
  425. });
  426. },
  427. // 下载二维码到本地
  428. downloadQrCode() {
  429. common_vendor.index.showLoading({
  430. title: "保存中..."
  431. });
  432. if (this.qrCodeUrl && this.qrCodeUrl.indexOf("data:image/png;base64,") === 0) {
  433. common_vendor.index.__f__("log", "at pages/travel-detail/index.vue:681", "检测到Base64格式图片,直接保存");
  434. const base64Data = this.qrCodeUrl.split(",")[1];
  435. try {
  436. const fs = common_vendor.wx$1.getFileSystemManager();
  437. const filePath = `${common_vendor.wx$1.env.USER_DATA_PATH}/trip_qrcode_${Date.now()}.png`;
  438. fs.writeFile({
  439. filePath,
  440. data: base64Data,
  441. encoding: "base64",
  442. success: () => {
  443. common_vendor.wx$1.saveImageToPhotosAlbum({
  444. filePath,
  445. success: () => {
  446. common_vendor.index.hideLoading();
  447. common_vendor.index.showToast({
  448. title: "保存成功",
  449. icon: "success"
  450. });
  451. },
  452. fail: (err) => {
  453. common_vendor.index.__f__("error", "at pages/travel-detail/index.vue:705", "保存到相册失败:", err);
  454. common_vendor.index.hideLoading();
  455. common_vendor.index.showToast({
  456. title: "保存失败",
  457. icon: "none"
  458. });
  459. }
  460. });
  461. },
  462. fail: (err) => {
  463. common_vendor.index.__f__("error", "at pages/travel-detail/index.vue:715", "写入文件失败:", err);
  464. common_vendor.index.hideLoading();
  465. common_vendor.index.showToast({
  466. title: "保存失败",
  467. icon: "none"
  468. });
  469. }
  470. });
  471. } catch (err) {
  472. common_vendor.index.__f__("error", "at pages/travel-detail/index.vue:724", "保存Base64图片失败:", err);
  473. common_vendor.index.hideLoading();
  474. common_vendor.index.showToast({
  475. title: "当前平台不支持保存",
  476. icon: "none"
  477. });
  478. }
  479. } else {
  480. common_vendor.index.downloadFile({
  481. url: this.qrCodeUrl,
  482. success: (res) => {
  483. if (res.statusCode === 200) {
  484. common_vendor.index.saveImageToPhotosAlbum({
  485. filePath: res.tempFilePath,
  486. success: () => {
  487. common_vendor.index.showToast({
  488. title: "保存成功",
  489. icon: "success"
  490. });
  491. },
  492. fail: (err) => {
  493. common_vendor.index.__f__("error", "at pages/travel-detail/index.vue:747", "保存到相册失败:", err);
  494. common_vendor.index.showToast({
  495. title: "保存失败",
  496. icon: "none"
  497. });
  498. }
  499. });
  500. }
  501. },
  502. fail: (err) => {
  503. common_vendor.index.__f__("error", "at pages/travel-detail/index.vue:757", "下载二维码失败:", err);
  504. common_vendor.index.showToast({
  505. title: "保存失败",
  506. icon: "none"
  507. });
  508. },
  509. complete: () => {
  510. common_vendor.index.hideLoading();
  511. }
  512. });
  513. }
  514. }
  515. }
  516. };
  517. function _sfc_render(_ctx, _cache, $props, $setup, $data, $options) {
  518. return common_vendor.e({
  519. a: $options.getTripCoverImage(),
  520. b: common_vendor.o((...args) => $options.goBack && $options.goBack(...args)),
  521. c: common_vendor.t($data.tripData.name || "保定精彩之旅"),
  522. d: common_vendor.t($data.tripData.days || "3"),
  523. e: common_vendor.t($data.tripData.days - 1 || "2"),
  524. f: common_vendor.t($options.formatDate($data.tripData.startDate)),
  525. g: common_vendor.t($data.tripData.days || "3"),
  526. h: common_vendor.t($data.tripData.days - 1 || "2"),
  527. i: common_vendor.t($options.formatDate($data.tripData.startDate)),
  528. j: $data.tripData.budget
  529. }, $data.tripData.budget ? {
  530. k: common_vendor.t($data.tripData.budget)
  531. } : {}, {
  532. l: common_vendor.t($data.tripData.peopleCount || 1),
  533. m: $data.tripData.spots && $data.tripData.spots.length > 0
  534. }, $data.tripData.spots && $data.tripData.spots.length > 0 ? {
  535. n: common_vendor.f($data.tripData.spots, (spot, index, i0) => {
  536. return common_vendor.e({
  537. a: common_vendor.t(index + 1),
  538. b: common_vendor.t(spot.name),
  539. c: spot.address
  540. }, spot.address ? {
  541. d: common_vendor.t(spot.address)
  542. } : {}, {
  543. e: index < $data.tripData.spots.length - 1
  544. }, index < $data.tripData.spots.length - 1 ? {
  545. f: common_vendor.t($options.getDistanceBetween(spot, $data.tripData.spots[index + 1]))
  546. } : {}, {
  547. g: index
  548. });
  549. })
  550. } : {}, {
  551. o: common_vendor.o((...args) => $options.editTrip && $options.editTrip(...args)),
  552. p: common_vendor.o((...args) => $options.goToHome && $options.goToHome(...args)),
  553. q: common_vendor.o((...args) => $options.shareTrip && $options.shareTrip(...args)),
  554. r: common_vendor.o((...args) => $options.showDeleteConfirm && $options.showDeleteConfirm(...args)),
  555. s: $data.showQrCode
  556. }, $data.showQrCode ? {
  557. t: common_vendor.o((...args) => $options.closeQrCode && $options.closeQrCode(...args)),
  558. v: $data.qrCodeUrl,
  559. w: common_vendor.t($data.tripData.name),
  560. x: common_vendor.t($data.tripData.days),
  561. y: common_vendor.t($data.tripData.budget),
  562. z: common_vendor.o((...args) => $options.saveQrCode && $options.saveQrCode(...args)),
  563. A: common_vendor.o(() => {
  564. }),
  565. B: common_vendor.o((...args) => $options.handlePopupBackdrop && $options.handlePopupBackdrop(...args))
  566. } : {});
  567. }
  568. const MiniProgramPage = /* @__PURE__ */ common_vendor._export_sfc(_sfc_main, [["render", _sfc_render]]);
  569. wx.createPage(MiniProgramPage);
  570. //# sourceMappingURL=../../../.sourcemap/mp-weixin/pages/travel-detail/index.js.map