图书馆小程序
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.

266 lines
7.4 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
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
1 month ago
2 months ago
1 month ago
1 month ago
1 month ago
2 months ago
1 month ago
2 months ago
1 month ago
2 months ago
1 month ago
1 month 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
  1. <template>
  2. <view class="item-container">
  3. <view v-if="bookList.length !== 0" class="count-text">
  4. <text>图书数量 ({{ bookList.length }})</text>
  5. </view>
  6. <view class="car-list" v-for="item in bookList" :key="item.barcode">
  7. <checkbox :checked="item.checked" @click="toggleItem(item)" />
  8. <view class="book-item-box">
  9. <view class="item-box-left">
  10. <image class="img-item" :src="defaultCover" mode="aspectFill" />
  11. </view>
  12. <view class="item-box-right">
  13. <view class="item-title line-clamp-2">{{ item.title || '暂无标题' }}</view>
  14. <view class="tag-box">
  15. <text class="item-author">{{ item.author || '佚名' }}</text>
  16. </view>
  17. <view class="item-desc">应还时间{{ item.returndate || '暂无' }}</view>
  18. </view>
  19. </view>
  20. </view>
  21. <view class="empty" v-if="bookList.length === 0">
  22. <uni-icons style="margin-left: 20px;" custom-prefix="iconfont" type="icon-kongshuju" size="80"></uni-icons>
  23. <text style="margin-top: 20px;">暂无相关数据</text>
  24. </view>
  25. <view class="bottom-placeholder"></view>
  26. <view class="car-bottom">
  27. <!-- 全选 -->
  28. <view class="all-check" @click="toggleAllCheck">
  29. <checkbox :checked="isAllChecked" />
  30. <text style="margin-left:6px">全选</text>
  31. </view>
  32. <button class="join-btn" @click="handleRenew" :disabled="!hasChecked">
  33. 一键续借
  34. </button>
  35. </view>
  36. </view>
  37. </template>
  38. <script>
  39. import { FetchInitScreenSetting } from '@/api/user';
  40. import { FetchRdloanlist, FetchRenewbook, FetchDeletebook } from '@/api/book';
  41. import { getCurrentReaderCard } from '@/utils/storage';
  42. export default {
  43. data() {
  44. return {
  45. bookList: [],
  46. defaultCover: '/static/images/default-book.png',
  47. screenConfig: {},
  48. };
  49. },
  50. onShow() {
  51. this.getConfigAndList();
  52. },
  53. computed: {
  54. // 全选状态
  55. isAllChecked() {
  56. return this.bookList.length > 0 && this.bookList.every(item => item.checked);
  57. },
  58. // 是否有选中
  59. hasChecked() {
  60. return this.bookList.some(item => item.checked);
  61. }
  62. },
  63. methods: {
  64. async getConfigAndList() {
  65. try {
  66. const res = await FetchInitScreenSetting({ libcode: '1201' });
  67. this.screenConfig = {
  68. thirdUrl: res.data.open_lib_http?.context || '',
  69. thirdAppid: res.data.open_lib_appId?.context || '',
  70. thirdSecret: res.data.open_lib_secret?.context || '',
  71. sm4Key: res.data.sm4_key?.context || '',
  72. opuser: res.data.op_user?.context || 'JH001',
  73. };
  74. const currentReaderCard = await getCurrentReaderCard();
  75. if (currentReaderCard) {
  76. this.isBindLibraryCard = true;
  77. this.getLendingList();
  78. } else {
  79. this.isBindLibraryCard = false;
  80. this.bookList = [];
  81. uni.showModal({
  82. title: '提示',
  83. content: '请您绑定读者证',
  84. confirmText: '去绑定',
  85. cancelText: '取消',
  86. success: (res) => {
  87. if (res.confirm) {
  88. uni.navigateTo({ url: "/pages/login/login" });
  89. } else {
  90. uni.switchTab({ url: "/pages/home/home" });
  91. }
  92. }
  93. });
  94. }
  95. } catch (err) {}
  96. },
  97. async getLendingList() {
  98. try {
  99. // 使用带缓存降级的函数获取读者证
  100. const currentReaderCard = await getCurrentReaderCard();
  101. console.log('当前证:', currentReaderCard);
  102. const params = {
  103. ...this.screenConfig,
  104. rdid: currentReaderCard.bindValue,
  105. };
  106. const res = await FetchRdloanlist(params);
  107. const result = typeof res.data === 'string' ? JSON.parse(res.data) : res.data;
  108. // 每条数据加 checked: false 购物车选中状态
  109. this.bookList = (result.loanlist || []).map(item => ({
  110. ...item,
  111. checked: false
  112. }));
  113. } catch (err) {
  114. uni.showToast({ title: '加载失败', icon: 'none' });
  115. }
  116. },
  117. // 单个勾选(购物车逻辑)
  118. toggleItem(item) {
  119. item.checked = !item.checked;
  120. },
  121. // 全选/取消全选
  122. toggleAllCheck() {
  123. const isAll = this.isAllChecked;
  124. this.bookList.forEach(item => {
  125. item.checked = !isAll;
  126. });
  127. },
  128. // 一键续借
  129. async handleRenew() {
  130. const checkedBooks = this.bookList.filter(item => item.checked);
  131. if (checkedBooks.length === 0) {
  132. uni.showToast({ title: '请选择图书', icon: 'none' });
  133. return;
  134. }
  135. const barcodes = checkedBooks.map(item => item.barcode).join('|');
  136. uni.showLoading({ title: '续借中...' });
  137. try {
  138. // 使用带缓存降级的函数获取读者证
  139. const currentReaderCard = await getCurrentReaderCard();
  140. const params = {
  141. ...this.screenConfig,
  142. rdid: currentReaderCard.bindValue,
  143. barcode: barcodes,
  144. logtype: '30007'
  145. };
  146. const res = await FetchRenewbook(params);
  147. // 解析接口返回的 data 字符串
  148. const result = typeof res.data === 'string' ? JSON.parse(res.data) : res.data;
  149. uni.hideLoading();
  150. if (result.success === true) {
  151. // 续借成功
  152. uni.showToast({
  153. title: `续借成功!`,
  154. icon: 'success'
  155. });
  156. // 刷新列表
  157. this.getLendingList();
  158. } else {
  159. // 续借失败 → 取后台提示信息
  160. let msg = '续借失败';
  161. if (result.messagelist && result.messagelist.length > 0) {
  162. msg = result.messagelist[0].message;
  163. }
  164. uni.showToast({
  165. title: msg,
  166. icon: 'none',
  167. duration: 3000
  168. });
  169. }
  170. } catch (err) {
  171. uni.hideLoading();
  172. uni.showToast({ title: '网络异常,续借失败', icon: 'none' });
  173. console.error('续借异常:', err);
  174. }
  175. },
  176. }
  177. };
  178. </script>
  179. <style lang="scss" scoped>
  180. .item-container {
  181. padding: 10px;
  182. background: #f5f6f7;
  183. min-height: 100vh;
  184. overflow: hidden;
  185. }
  186. .count-text {
  187. margin-bottom: 10px;
  188. font-size: 14px;
  189. color: #333;
  190. }
  191. .car-list {
  192. display: flex;
  193. align-items: flex-start;
  194. overflow-y: auto;
  195. margin-bottom: 10px;
  196. checkbox {
  197. margin-top: 15px;
  198. padding: 0 10px;
  199. }
  200. }
  201. .book-item-box {
  202. flex: 1;
  203. background: #fff;
  204. border-radius: 8px;
  205. padding: 12px;
  206. display: flex;
  207. .item-box-left {
  208. margin-right: 12px;
  209. .img-item {
  210. width: 64px;
  211. height: 90px;
  212. border-radius: 6px;
  213. }
  214. }
  215. .item-box-right { flex: 1; }
  216. .item-title { font-weight: bold; margin-bottom: 4px; }
  217. .item-author {
  218. font-size: 12px; background: #f4f6fc;
  219. padding: 2px 6px; border-radius: 4px; margin-right: 6px;
  220. }
  221. .item-desc { font-size: 12px; color: #999; margin-top: 6px; }
  222. }
  223. .bottom-placeholder { height: 60px; }
  224. .car-bottom {
  225. position: fixed; left: 0; bottom: 0; right: 0;
  226. background: #fff; padding: 12px 15px;
  227. display: flex; justify-content: space-between; align-items: center;
  228. box-shadow: 0 -2px 5px rgba(0,0,0,0.05);
  229. }
  230. .all-check { display: flex; align-items: center; }
  231. .join-btn {
  232. font-size: 14px; color: #fff;
  233. background: #01a4fe !important; border-radius: 23px;
  234. padding: 0 30px;
  235. &::after{ border: none !important; }
  236. &[disabled] { background: #ccc !important; }
  237. }
  238. .empty {
  239. padding: 0 !important;
  240. height: calc(100vh - 80px);
  241. }
  242. </style>