图书馆小程序
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

341 lines
8.8 KiB

2 months ago
1 month ago
2 months ago
1 month ago
2 months ago
1 month ago
2 months ago
1 month ago
2 months ago
1 month ago
2 months ago
1 month ago
2 months ago
1 month ago
2 months ago
1 month ago
2 months ago
1 month ago
2 months ago
1 month ago
2 months ago
1 month ago
2 months ago
1 month ago
2 months ago
1 month ago
2 months ago
2 months ago
1 month ago
2 months ago
1 month ago
2 months ago
1 month ago
2 months ago
1 month ago
2 months ago
1 month ago
2 months ago
1 month ago
2 months ago
1 month ago
2 months ago
1 month ago
2 months ago
1 month ago
2 months ago
1 month ago
2 months ago
2 months ago
1 month ago
2 months ago
2 months ago
2 months ago
2 months ago
2 months ago
1 month ago
2 months ago
  1. <template>
  2. <view class="detail-container">
  3. <!-- 书籍头部信息 -->
  4. <view class="article-detail-container">
  5. <view class="article-detail-left">
  6. <view class="article-detail-title">{{ bookInfo.title || bookInfo.name || '暂无书名' }}</view>
  7. <view class="article-detail-info">
  8. <view class="article-detail-author">作者{{ bookInfo.author || '暂无' }}</view>
  9. <view class="article-detail-time">出版社{{ bookInfo.publisher || '暂无' }}</view>
  10. <view class="article-detail-time">ISBN{{ bookInfo.isbn || '暂无' }}</view>
  11. <!-- <view class="article-detail-time">出版时间{{ bookInfo.publishdate || '暂无' }}</view> -->
  12. </view>
  13. </view>
  14. <view class="article-detail-right">
  15. <!-- <image
  16. :src="bookInfo.imgPath
  17. ? baseUrl + '/api/fileRelevant/getImg?imgType=2&imgId=' + bookInfo.imgPath
  18. : bookInfo.cover || '/static/images/default-book.png'"
  19. mode="widthFix"
  20. /> -->
  21. <image
  22. class="img-item"
  23. :src="bookInfo.cover || (bookInfo.imgPath ? baseUrl + '/api/fileRelevant/getImg?imgType=2&imgId=' + bookInfo.imgPath : '/static/images/default-book.png')"
  24. mode="widthFix"
  25. @error="onImgError"
  26. ></image>
  27. </view>
  28. </view>
  29. <!-- 馆藏信息 -->
  30. <view class="book-store-info">
  31. <view class="book-store-info-item">
  32. <text class="store-txt1">{{ bookInfo.orglib || '暂无' }}</text>
  33. <text class="store-txt2">所属馆</text>
  34. </view>
  35. <view class="book-store-info-item">
  36. <text class="store-txt1">{{ bookInfo.loancount || 0 }}</text>
  37. <text class="store-txt2">在馆</text>
  38. </view>
  39. <!-- 编目=1,在馆=2,借出=3,丢失=4,剔除=5,交换=6,赠送=7,装订=8,锁定=9,预借=10 清点=12 -->
  40. <view class="book-store-info-item">
  41. <text class="store-txt1">{{ stateText }}</text>
  42. <text class="store-txt2">馆藏状态</text>
  43. </view>
  44. </view>
  45. <!-- 索书号/条码号 -->
  46. <view v-if="bookInfo.collection" class="store-info-list">
  47. <view class="store-info-item" v-for="(item, index) in bookInfo.collection" :key="index">
  48. <view>
  49. <text>索书号</text>
  50. <text>{{ item.callno || '暂无' }}</text>
  51. </view>
  52. <view>
  53. <text>条码号</text>
  54. <text>{{ item.barcode || '暂无' }}</text>
  55. </view>
  56. </view>
  57. </view>
  58. <!-- TAB 选项卡 -->
  59. <view class="content-tab">
  60. <view class="tab-item" :class="{active: currentTab === 0}" @click="currentTab = 0">
  61. 内容简介
  62. </view>
  63. <view class="tab-item" :class="{active: currentTab === 1}" @click="currentTab = 1">
  64. 作者简介
  65. </view>
  66. </view>
  67. <!-- TAB 内容 -->
  68. <view class="content-item" v-if="currentTab === 0">
  69. {{ bookInfo.summary || bookInfo.explain || '暂无内容简介' }}
  70. </view>
  71. <view class="content-item" v-if="currentTab === 1">
  72. {{ bookInfo.authorbio || '暂无作者简介' }}
  73. </view>
  74. <view class="detail-bottom">
  75. <button open-type="share" class="handle-btn">
  76. <uni-icons custom-prefix="iconfont" type="icon-fenxiang01" size="20"></uni-icons>
  77. <text class="share-text">分享</text>
  78. </button>
  79. <button class="handle-btn" @click="toggleCollect">
  80. <uni-icons :type="isCollected ? 'heart-filled' : 'heart'" size="20" color="#ff4444"></uni-icons>
  81. <text class="share-text">{{ isCollected ? '已收藏' : '收藏' }}</text>
  82. </button>
  83. </view>
  84. </view>
  85. </template>
  86. <script>
  87. import { FetchInitScreenSetting } from '@/api/user';
  88. import { FetchFindbookByQuery } from '@/api/book';
  89. import config from '@/utils/config';
  90. export default {
  91. data() {
  92. return {
  93. baseUrl: config.baseUrl,
  94. currentTab: 0,
  95. isCollected: false,
  96. bookrecno: '',
  97. opacUrl: '',
  98. bookInfo: {} // 图书详情
  99. };
  100. },
  101. onLoad(options) {
  102. // 接收从首页带过来的完整图书数据
  103. if (options.bookData) {
  104. const bookData = JSON.parse(decodeURIComponent(options.bookData));
  105. this.bookInfo = bookData; // 直接赋值渲染
  106. this.bookrecno = bookData.bookrecno || "";
  107. this.checkCollectStatus();
  108. return;
  109. }
  110. // 如果是从检索页过来(走bookrecno请求)
  111. this.bookrecno = options.bookrecno || "";
  112. this.getOpacUrl();
  113. },
  114. computed: {
  115. // 馆藏状态转换:数字 → 文字
  116. stateText() {
  117. const state = this.bookInfo.state || 0
  118. const map = {
  119. 1: '编目',
  120. 2: '在馆',
  121. 3: '借出',
  122. 4: '丢失',
  123. 5: '剔除',
  124. 6: '交换',
  125. 7: '赠送',
  126. 8: '装订',
  127. 9: '锁定',
  128. 10: '预借',
  129. 12: '清点'
  130. }
  131. return map[state] || '未知'
  132. }
  133. },
  134. methods: {
  135. onImgError(e) {
  136. e.target.src = "/static/images/default-book.png";
  137. },
  138. // 获取配置
  139. async getOpacUrl() {
  140. try {
  141. const res = await FetchInitScreenSetting({ libcode: '1201' });
  142. this.opacUrl = res.data.opac_url?.context || '';
  143. this.getBookDetail();
  144. } catch (err) {}
  145. },
  146. // 获取图书详情
  147. async getBookDetail() {
  148. if (!this.bookrecno || !this.opacUrl) return;
  149. uni.showLoading({ title: '加载中...' });
  150. try {
  151. const params = {
  152. opacUrl: this.opacUrl,
  153. bookrecno: this.bookrecno
  154. };
  155. const res = await FetchFindbookByQuery(params);
  156. // 解析数据
  157. let detail = {};
  158. if (typeof res.data === 'string') {
  159. detail = JSON.parse(res.data);
  160. } else {
  161. detail = res.data || {};
  162. }
  163. this.bookInfo = detail;
  164. this.checkCollectStatus();
  165. } catch (err) {
  166. } finally {
  167. uni.hideLoading();
  168. }
  169. },
  170. // 收藏逻辑
  171. checkCollectStatus() {
  172. const list = uni.getStorageSync('collectList') || [];
  173. this.isCollected = list.includes(this.bookrecno);
  174. },
  175. toggleCollect() {
  176. let list = uni.getStorageSync('collectList') || [];
  177. if (this.isCollected) {
  178. list = list.filter(i => i !== this.bookrecno);
  179. uni.showToast({ title: '取消收藏', icon: 'success' });
  180. } else {
  181. list.push(this.bookrecno);
  182. uni.showToast({ title: '收藏成功', icon: 'success' });
  183. }
  184. uni.setStorageSync('collectList', list);
  185. this.isCollected = !this.isCollected;
  186. }
  187. },
  188. onShareAppMessage() {
  189. return {
  190. title: this.bookInfo.title || '图书详情',
  191. path: '/subpkg/pages/book-detail/book-detail?bookrecno=' + this.bookrecno,
  192. imageUrl: this.bookInfo.cover
  193. };
  194. }
  195. };
  196. </script>
  197. <style lang="scss" scoped>
  198. .detail-container {
  199. padding: 15px;
  200. background-color: #f5f5f5;
  201. min-height: 100vh;
  202. padding-bottom: 60px;
  203. }
  204. /* 书籍信息 */
  205. .article-detail-container {
  206. display: flex;
  207. background-color: #fff;
  208. border-radius: 10px;
  209. padding: 20px;
  210. margin-bottom: 12px;
  211. }
  212. .article-detail-left {
  213. flex: 1;
  214. }
  215. .article-detail-title {
  216. font-size: 20px;
  217. font-weight: bold;
  218. color: #333;
  219. margin-bottom: 10px;
  220. }
  221. .article-detail-info {
  222. font-size: 14px;
  223. color: #666;
  224. line-height: 1.5;
  225. }
  226. .article-detail-right {
  227. width: 110px;
  228. height: 150px;
  229. margin-left: 15px;
  230. }
  231. .article-detail-right image {
  232. width: 100%;
  233. height: 100%;
  234. border-radius: 6px;
  235. box-shadow: 0 2px 8px rgba(0,0,0,0.1);
  236. }
  237. /* 馆藏统计 */
  238. .book-store-info {
  239. background-color: #fff;
  240. border-radius: 10px;
  241. padding: 20px;
  242. display: flex;
  243. justify-content: space-around;
  244. margin-bottom: 12px;
  245. }
  246. .book-store-info-item {
  247. display: flex;
  248. flex-direction: column;
  249. align-items: center;
  250. }
  251. .store-txt1 {
  252. font-size: 22px;
  253. font-weight: bold;
  254. color: #2b85e4;
  255. }
  256. .store-txt2 {
  257. font-size: 13px;
  258. color: #999;
  259. margin-top: 4px;
  260. }
  261. /* 索书号 */
  262. .store-info-list {
  263. background-color: #fff;
  264. border-radius: 10px;
  265. padding: 20px;
  266. margin-bottom: 15px;
  267. }
  268. .store-info-item {
  269. display: flex;
  270. justify-content: space-between;
  271. font-size: 14px;
  272. color: #666;
  273. }
  274. .store-info-item view {
  275. display: flex;
  276. flex-direction: column;
  277. align-items: center;
  278. }
  279. /* TAB */
  280. .content-tab {
  281. display: flex;
  282. background-color: #fff;
  283. border-radius: 10px;
  284. overflow: hidden;
  285. margin-bottom: 12px;
  286. }
  287. .tab-item {
  288. flex: 1;
  289. text-align: center;
  290. padding: 15px 0;
  291. font-size: 15px;
  292. color: #666;
  293. position: relative;
  294. }
  295. .tab-item.active {
  296. color: #2b85e4;
  297. font-weight: bold;
  298. }
  299. .tab-item.active::after {
  300. content: "";
  301. position: absolute;
  302. bottom: 0;
  303. left: 50%;
  304. transform: translateX(-50%);
  305. width: 30px;
  306. height: 3px;
  307. background-color: #2b85e4;
  308. border-radius: 2px;
  309. }
  310. /* 内容区域 */
  311. .content-item {
  312. background-color: #fff;
  313. border-radius: 10px;
  314. padding: 20px;
  315. font-size: 15px;
  316. color: #333;
  317. line-height: 1.6;
  318. }
  319. .detail-bottom{
  320. justify-content: space-around;
  321. }
  322. </style>