book-detail.js 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393
  1. "use strict";
  2. const common_vendor = require("../../common/vendor.js");
  3. const utils_api = require("../../utils/api.js");
  4. const _sfc_main = {
  5. data() {
  6. return {
  7. bookInfo: {
  8. id: null,
  9. title: "",
  10. image: "",
  11. cover: "",
  12. brief: "",
  13. desc: "",
  14. author: "",
  15. isFree: false,
  16. price: 0,
  17. introduction: ""
  18. },
  19. isLoading: false,
  20. userInfo: null,
  21. isInShelf: false,
  22. reviews: [],
  23. recommendBooks: []
  24. };
  25. },
  26. onLoad(options) {
  27. try {
  28. const userInfo = common_vendor.index.getStorageSync("userInfo");
  29. if (userInfo && userInfo.id) {
  30. this.userInfo = userInfo;
  31. }
  32. } catch (e) {
  33. common_vendor.index.__f__("error", "at pages/book-detail/book-detail.vue:131", "获取用户信息失败", e);
  34. }
  35. if (options.bookId) {
  36. this.bookInfo.id = parseInt(options.bookId);
  37. this.loadBookDetail(this.bookInfo.id);
  38. } else if (options.title) {
  39. this.bookInfo.title = decodeURIComponent(options.title);
  40. if (options.image) {
  41. this.bookInfo.image = decodeURIComponent(options.image);
  42. }
  43. if (options.author) {
  44. this.bookInfo.author = decodeURIComponent(options.author);
  45. }
  46. if (options.bookId) {
  47. this.bookInfo.id = parseInt(options.bookId);
  48. this.loadBookDetail(this.bookInfo.id);
  49. }
  50. }
  51. },
  52. onShow() {
  53. try {
  54. const userInfo = common_vendor.index.getStorageSync("userInfo");
  55. if (userInfo && userInfo.id) {
  56. this.userInfo = userInfo;
  57. if (this.bookInfo.id) {
  58. this.checkBookshelfStatus(userInfo.id, this.bookInfo.id);
  59. this.loadComments(this.bookInfo.id);
  60. }
  61. }
  62. } catch (e) {
  63. common_vendor.index.__f__("error", "at pages/book-detail/book-detail.vue:169", "获取用户信息失败", e);
  64. }
  65. },
  66. methods: {
  67. goBack() {
  68. common_vendor.index.navigateBack();
  69. },
  70. handleShare() {
  71. common_vendor.index.showToast({
  72. title: "分享功能",
  73. icon: "none"
  74. });
  75. },
  76. async loadBookDetail(bookId) {
  77. if (!bookId) {
  78. common_vendor.index.showToast({
  79. title: "书籍ID不能为空",
  80. icon: "none"
  81. });
  82. return;
  83. }
  84. try {
  85. this.isLoading = true;
  86. common_vendor.index.showLoading({
  87. title: "加载中...",
  88. mask: false
  89. });
  90. const userId = this.userInfo && this.userInfo.id ? this.userInfo.id : null;
  91. const res = await utils_api.getBookById(bookId, userId);
  92. if (res && res.code === 200 && res.data) {
  93. const book = res.data;
  94. this.bookInfo = {
  95. id: book.id,
  96. title: book.title || "",
  97. image: book.image || book.cover || "",
  98. cover: book.cover || book.image || "",
  99. brief: book.brief || "",
  100. desc: book.desc || book.brief || "",
  101. author: book.author || "",
  102. isFree: book.isFree || false,
  103. price: book.price || 0,
  104. introduction: book.introduction || book.desc || book.brief || ""
  105. };
  106. if (!this.bookInfo.brief && this.bookInfo.desc) {
  107. this.bookInfo.brief = this.bookInfo.desc;
  108. }
  109. if (!this.bookInfo.introduction) {
  110. this.bookInfo.introduction = this.bookInfo.desc || this.bookInfo.brief || "";
  111. }
  112. if (this.userInfo && this.userInfo.id) {
  113. this.checkBookshelfStatus(this.userInfo.id, bookId);
  114. }
  115. this.loadRecommendBooks();
  116. if (this.userInfo && this.userInfo.id) {
  117. this.recordBrowsingHistory(this.userInfo.id, bookId);
  118. }
  119. this.loadComments(bookId);
  120. } else {
  121. common_vendor.index.showToast({
  122. title: res.message || "加载失败",
  123. icon: "none"
  124. });
  125. }
  126. } catch (e) {
  127. common_vendor.index.__f__("error", "at pages/book-detail/book-detail.vue:250", "加载书籍详情失败:", e);
  128. common_vendor.index.showToast({
  129. title: e.message || "加载失败,请重试",
  130. icon: "none"
  131. });
  132. } finally {
  133. this.isLoading = false;
  134. common_vendor.index.hideLoading();
  135. }
  136. },
  137. async loadRecommendBooks() {
  138. try {
  139. const res = await utils_api.getMoreRecommend(6);
  140. if (res && res.code === 200 && res.data && Array.isArray(res.data)) {
  141. this.recommendBooks = res.data.filter((book) => book.id !== this.bookInfo.id).slice(0, 6).map((book) => ({
  142. id: book.id,
  143. title: book.title || "",
  144. image: book.image || book.cover || ""
  145. }));
  146. }
  147. } catch (e) {
  148. common_vendor.index.__f__("error", "at pages/book-detail/book-detail.vue:275", "加载推荐书籍失败:", e);
  149. }
  150. },
  151. handleWriteReview() {
  152. common_vendor.index.navigateTo({
  153. url: `/pages/write-review/write-review?bookId=${this.bookInfo.id}&title=${encodeURIComponent(this.bookInfo.title)}`
  154. });
  155. },
  156. async toggleLike(review, index) {
  157. if (!this.userInfo || !this.userInfo.id) {
  158. common_vendor.index.showToast({
  159. title: "请先登录",
  160. icon: "none"
  161. });
  162. return;
  163. }
  164. try {
  165. const res = await utils_api.toggleCommentLike(this.userInfo.id, review.id);
  166. if (res && res.code === 200) {
  167. this.reviews[index].isLiked = res.data;
  168. if (res.data) {
  169. this.reviews[index].likes++;
  170. } else {
  171. this.reviews[index].likes--;
  172. }
  173. } else {
  174. common_vendor.index.showToast({
  175. title: res.message || "操作失败",
  176. icon: "none"
  177. });
  178. }
  179. } catch (e) {
  180. common_vendor.index.__f__("error", "at pages/book-detail/book-detail.vue:311", "点赞失败", e);
  181. common_vendor.index.showToast({
  182. title: "操作失败,请重试",
  183. icon: "none"
  184. });
  185. }
  186. },
  187. async loadComments(bookId) {
  188. if (!bookId) {
  189. return;
  190. }
  191. try {
  192. const userId = this.userInfo && this.userInfo.id ? this.userInfo.id : null;
  193. const res = await utils_api.getComments(bookId, userId);
  194. if (res && res.code === 200 && res.data) {
  195. this.reviews = res.data.map((item) => ({
  196. id: item.id,
  197. name: item.name || "匿名用户",
  198. avatar: item.avatar || "https://via.placeholder.com/100x100?text=User",
  199. isRecommended: item.isRecommended || false,
  200. date: item.date || "",
  201. likes: item.likes || 0,
  202. isLiked: item.isLiked || false,
  203. content: item.content || ""
  204. }));
  205. }
  206. } catch (e) {
  207. common_vendor.index.__f__("error", "at pages/book-detail/book-detail.vue:340", "加载评论失败", e);
  208. }
  209. },
  210. async recordBrowsingHistory(userId, bookId) {
  211. if (!userId || !bookId) {
  212. return;
  213. }
  214. try {
  215. await utils_api.recordBrowsingHistory(userId, bookId);
  216. } catch (e) {
  217. common_vendor.index.__f__("error", "at pages/book-detail/book-detail.vue:352", "记录浏览历史失败", e);
  218. }
  219. },
  220. viewAllReviews() {
  221. common_vendor.index.showToast({
  222. title: "查看全部书评",
  223. icon: "none"
  224. });
  225. },
  226. viewMoreRecommend() {
  227. common_vendor.index.showToast({
  228. title: "查看更多推荐",
  229. icon: "none"
  230. });
  231. },
  232. goToBookDetail(book) {
  233. if (!book || !book.id) {
  234. common_vendor.index.showToast({
  235. title: "书籍信息不完整",
  236. icon: "none"
  237. });
  238. return;
  239. }
  240. common_vendor.index.navigateTo({
  241. url: `/pages/book-detail/book-detail?bookId=${book.id}`
  242. });
  243. },
  244. // 检查书架状态
  245. checkBookshelfStatus(userId, bookId) {
  246. if (!userId || !bookId) {
  247. return;
  248. }
  249. utils_api.checkInBookshelf(userId, bookId).then((res) => {
  250. if (res.code === 200 && res.data !== void 0) {
  251. this.isInShelf = res.data;
  252. }
  253. }).catch((err) => {
  254. common_vendor.index.__f__("error", "at pages/book-detail/book-detail.vue:393", "检查书架状态失败", err);
  255. });
  256. },
  257. handleAddToShelf() {
  258. if (!this.userInfo || !this.userInfo.id) {
  259. common_vendor.index.showModal({
  260. title: "提示",
  261. content: "请先登录",
  262. showCancel: true,
  263. cancelText: "取消",
  264. confirmText: "去登录",
  265. success: (res) => {
  266. if (res.confirm) {
  267. common_vendor.index.navigateTo({
  268. url: "/pages/login/login"
  269. });
  270. }
  271. }
  272. });
  273. return;
  274. }
  275. if (this.isInShelf) {
  276. common_vendor.index.showToast({
  277. title: "已在书架中",
  278. icon: "none"
  279. });
  280. return;
  281. }
  282. if (!this.bookInfo.id) {
  283. common_vendor.index.showToast({
  284. title: "书籍信息不完整",
  285. icon: "none"
  286. });
  287. return;
  288. }
  289. if (this.isLoading) {
  290. return;
  291. }
  292. this.isLoading = true;
  293. common_vendor.index.showLoading({
  294. title: "加入中...",
  295. mask: true
  296. });
  297. utils_api.addToBookshelf(this.userInfo.id, this.bookInfo.id).then((res) => {
  298. common_vendor.index.hideLoading();
  299. this.isLoading = false;
  300. if (res.code === 200) {
  301. this.isInShelf = true;
  302. common_vendor.index.showToast({
  303. title: "已加入书架",
  304. icon: "success"
  305. });
  306. } else {
  307. common_vendor.index.showToast({
  308. title: res.message || "加入失败",
  309. icon: "none"
  310. });
  311. }
  312. }).catch((err) => {
  313. common_vendor.index.hideLoading();
  314. this.isLoading = false;
  315. common_vendor.index.__f__("error", "at pages/book-detail/book-detail.vue:468", "加入书架失败:", err);
  316. common_vendor.index.showToast({
  317. title: err.message || "加入失败,请检查网络连接",
  318. icon: "none",
  319. duration: 2e3
  320. });
  321. });
  322. },
  323. handleRead() {
  324. common_vendor.index.navigateTo({
  325. url: `/pages/book-cover/book-cover?bookId=${this.bookInfo.id}&title=${encodeURIComponent(this.bookInfo.title)}&image=${encodeURIComponent(this.bookInfo.image)}&author=${encodeURIComponent(this.bookInfo.author)}`
  326. });
  327. }
  328. }
  329. };
  330. function _sfc_render(_ctx, _cache, $props, $setup, $data, $options) {
  331. return common_vendor.e({
  332. a: common_vendor.o((...args) => $options.goBack && $options.goBack(...args)),
  333. b: common_vendor.t($data.bookInfo.title),
  334. c: common_vendor.o((...args) => $options.handleShare && $options.handleShare(...args)),
  335. d: !$data.isLoading
  336. }, !$data.isLoading ? common_vendor.e({
  337. e: $data.bookInfo.image || $data.bookInfo.cover,
  338. f: common_vendor.t($data.bookInfo.title),
  339. g: $data.bookInfo.brief || $data.bookInfo.desc
  340. }, $data.bookInfo.brief || $data.bookInfo.desc ? {
  341. h: common_vendor.t($data.bookInfo.brief || $data.bookInfo.desc)
  342. } : {}, {
  343. i: $data.bookInfo.author
  344. }, $data.bookInfo.author ? {
  345. j: common_vendor.t($data.bookInfo.author)
  346. } : {}, {
  347. k: $data.bookInfo.isFree
  348. }, $data.bookInfo.isFree ? {} : $data.bookInfo.price ? {
  349. m: common_vendor.t($data.bookInfo.price)
  350. } : {}, {
  351. l: $data.bookInfo.price
  352. }) : {}, {
  353. n: $data.isLoading
  354. }, $data.isLoading ? {} : {}, {
  355. o: $data.bookInfo.introduction || $data.bookInfo.desc || $data.bookInfo.brief
  356. }, $data.bookInfo.introduction || $data.bookInfo.desc || $data.bookInfo.brief ? {
  357. p: common_vendor.t($data.bookInfo.introduction || $data.bookInfo.desc || $data.bookInfo.brief)
  358. } : {}, {
  359. q: common_vendor.o((...args) => $options.handleWriteReview && $options.handleWriteReview(...args)),
  360. r: common_vendor.f($data.reviews, (review, index, i0) => {
  361. return common_vendor.e({
  362. a: review.avatar,
  363. b: common_vendor.t(review.name),
  364. c: review.isRecommended
  365. }, review.isRecommended ? {} : {}, {
  366. d: common_vendor.t(review.date),
  367. e: common_vendor.t(review.isLiked ? "❤️" : "🤍"),
  368. f: common_vendor.t(review.likes),
  369. g: common_vendor.o(($event) => $options.toggleLike(review, index), index),
  370. h: common_vendor.t(review.content),
  371. i: index
  372. });
  373. }),
  374. s: common_vendor.o((...args) => $options.viewAllReviews && $options.viewAllReviews(...args)),
  375. t: common_vendor.o((...args) => $options.viewMoreRecommend && $options.viewMoreRecommend(...args)),
  376. v: common_vendor.f($data.recommendBooks, (book, index, i0) => {
  377. return {
  378. a: book.image,
  379. b: common_vendor.t(book.title),
  380. c: index,
  381. d: common_vendor.o(($event) => $options.goToBookDetail(book), index)
  382. };
  383. }),
  384. w: common_vendor.t($data.isInShelf ? "已在书架" : "加入书架"),
  385. x: $data.isInShelf ? 1 : "",
  386. y: common_vendor.o((...args) => $options.handleAddToShelf && $options.handleAddToShelf(...args)),
  387. z: $data.isLoading,
  388. A: common_vendor.o((...args) => $options.handleRead && $options.handleRead(...args))
  389. });
  390. }
  391. const MiniProgramPage = /* @__PURE__ */ common_vendor._export_sfc(_sfc_main, [["render", _sfc_render], ["__scopeId", "data-v-ac1886ed"]]);
  392. wx.createPage(MiniProgramPage);
  393. //# sourceMappingURL=../../../.sourcemap/mp-weixin/pages/book-detail/book-detail.js.map