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

237 lines
6.4 KiB

6 months ago
​
6 months ago
6 months ago
​
​
6 months ago
​
​
​
​
​
​
​
​
​
​
6 months ago
6 months ago
6 months ago
​
6 months ago
6 months ago
6 months ago
​
​
​
​
6 months ago
​
​
​
6 months ago
6 months ago
​
​
​
6 months ago
​
6 months ago
​
​
​
​
​
6 months ago
​
​
6 months ago
​
​
6 months ago
​
​
6 months ago
​
6 months ago
​
​
6 months ago
6 months ago
6 months ago
6 months ago
6 months ago
​
​
6 months ago
​
6 months ago
​
6 months ago
​
​
​
​
​
​
​
​
​
​
​
6 months ago
6 months ago
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
6 months ago
​
6 months ago
​
​
​
​
​
​
​
6 months ago
6 months ago
6 months ago
​
​
​
​
6 months ago
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
6 months ago
6 months ago
6 months ago
​
​
​
​
​
​
​
6 months ago
6 months ago
​
​
​
6 months ago
6 months ago
​
​
​
6 months ago
6 months ago
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
6 months ago
​
​
​
​
6 months ago
6 months ago
6 months ago
6 months ago
6 months ago
6 months ago
​
​
​
6 months ago
6 months ago
6 months ago
6 months ago
​
6 months ago
6 months ago
​
6 months ago
6 months ago
​
​
​
6 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 } from '@/api/book';
  41. export default {
  42. data() {
  43. return {
  44. bookList: [],
  45. defaultCover: '/static/images/default-book.png',
  46. screenConfig: {},
  47. };
  48. },
  49. onLoad() {
  50. this.getConfigAndList();
  51. },
  52. computed: {
  53. // 全选状态
  54. isAllChecked() {
  55. return this.bookList.length > 0 && this.bookList.every(item => item.checked);
  56. },
  57. // 是否有选中
  58. hasChecked() {
  59. return this.bookList.some(item => item.checked);
  60. }
  61. },
  62. methods: {
  63. async getConfigAndList() {
  64. try {
  65. const res = await FetchInitScreenSetting({ libcode: '1201' });
  66. this.screenConfig = {
  67. thirdUrl: res.data.open_lib_http?.context || '',
  68. thirdAppid: res.data.open_lib_appId?.context || '',
  69. thirdSecret: res.data.open_lib_secret?.context || '',
  70. sm4Key: res.data.sm4_key?.context || '',
  71. opuser: res.data.op_user?.context || 'JH001',
  72. };
  73. this.getLendingList();
  74. } catch (err) {}
  75. },
  76. async getLendingList() {
  77. try {
  78. const params = {
  79. ...this.screenConfig,
  80. rdid: uni.getStorageSync('currentReaderCard'),
  81. };
  82. const res = await FetchRdloanlist(params);
  83. const result = typeof res.data === 'string' ? JSON.parse(res.data) : res.data;
  84. // 每条数据加 checked: false 购物车选中状态
  85. this.bookList = (result.loanlist || []).map(item => ({
  86. ...item,
  87. checked: false
  88. }));
  89. } catch (err) {
  90. uni.showToast({ title: '加载失败', icon: 'none' });
  91. }
  92. },
  93. // 单个勾选(购物车逻辑)
  94. toggleItem(item) {
  95. item.checked = !item.checked;
  96. },
  97. // 全选/取消全选
  98. toggleAllCheck() {
  99. const isAll = this.isAllChecked;
  100. this.bookList.forEach(item => {
  101. item.checked = !isAll;
  102. });
  103. },
  104. // 一键续借
  105. async handleRenew() {
  106. const checkedBooks = this.bookList.filter(item => item.checked);
  107. if (checkedBooks.length === 0) {
  108. uni.showToast({ title: '请选择图书', icon: 'none' });
  109. return;
  110. }
  111. const barcodes = checkedBooks.map(item => item.barcode).join('|');
  112. uni.showLoading({ title: '续借中...' });
  113. try {
  114. const params = {
  115. ...this.screenConfig,
  116. rdid: uni.getStorageSync('currentReaderCard'),
  117. barcode: barcodes,
  118. logtype: '30007'
  119. };
  120. const res = await FetchRenewbook(params);
  121. // 解析接口返回的 data 字符串
  122. const result = typeof res.data === 'string' ? JSON.parse(res.data) : res.data;
  123. uni.hideLoading();
  124. if (result.success === true) {
  125. // 续借成功
  126. uni.showToast({
  127. title: `续借成功!`,
  128. icon: 'success'
  129. });
  130. // 刷新列表
  131. this.getLendingList();
  132. } else {
  133. // 续借失败 → 取后台提示信息
  134. let msg = '续借失败';
  135. if (result.messagelist && result.messagelist.length > 0) {
  136. msg = result.messagelist[0].message;
  137. }
  138. uni.showToast({
  139. title: msg,
  140. icon: 'none',
  141. duration: 3000
  142. });
  143. }
  144. } catch (err) {
  145. uni.hideLoading();
  146. uni.showToast({ title: '网络异常,续借失败', icon: 'none' });
  147. console.error('续借异常:', err);
  148. }
  149. },
  150. }
  151. };
  152. </script>
  153. <style lang="scss" scoped>
  154. .item-container {
  155. padding: 10px;
  156. background: #f5f6f7;
  157. min-height: 100vh;
  158. overflow: hidden;
  159. }
  160. .count-text {
  161. margin-bottom: 10px;
  162. font-size: 14px;
  163. color: #333;
  164. }
  165. .car-list {
  166. display: flex;
  167. align-items: flex-start;
  168. overflow-y: auto;
  169. margin-bottom: 10px;
  170. checkbox {
  171. margin-top: 15px;
  172. padding: 0 10px;
  173. }
  174. }
  175. .book-item-box {
  176. flex: 1;
  177. background: #fff;
  178. border-radius: 8px;
  179. padding: 12px;
  180. display: flex;
  181. .item-box-left {
  182. margin-right: 12px;
  183. .img-item {
  184. width: 64px;
  185. height: 90px;
  186. border-radius: 6px;
  187. }
  188. }
  189. .item-box-right { flex: 1; }
  190. .item-title { font-weight: bold; margin-bottom: 4px; }
  191. .item-author {
  192. font-size: 12px; background: #f4f6fc;
  193. padding: 2px 6px; border-radius: 4px; margin-right: 6px;
  194. }
  195. .item-desc { font-size: 12px; color: #999; margin-top: 6px; }
  196. }
  197. .bottom-placeholder { height: 60px; }
  198. .car-bottom {
  199. position: fixed; left: 0; bottom: 0; right: 0;
  200. background: #fff; padding: 12px 15px;
  201. display: flex; justify-content: space-between; align-items: center;
  202. box-shadow: 0 -2px 5px rgba(0,0,0,0.05);
  203. }
  204. .all-check { display: flex; align-items: center; }
  205. .join-btn {
  206. font-size: 14px; color: #fff;
  207. background: #01a4fe !important; border-radius: 23px;
  208. padding: 0 30px;
  209. &::after{ border: none !important; }
  210. &[disabled] { background: #ccc !important; }
  211. }
  212. .empty {
  213. padding: 0 !important;
  214. height: calc(100vh - 80px);
  215. }
  216. </style>