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

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