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

316 lines
6.9 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
1 month ago
2 months ago
1 month ago
2 months ago
1 month ago
1 month ago
1 month ago
1 month ago
1 month ago
1 month ago
1 month ago
1 month ago
1 month ago
1 month 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 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 style="background-color: #fff; padding-bottom:5px;">
  3. <view class="my-search-container">
  4. <view class="my-search-wrapper">
  5. <picker
  6. mode="selector"
  7. :range="rangeText"
  8. :value="selectIndex"
  9. @change="onPickerChange"
  10. class="picker-select"
  11. >
  12. <view class="picker-display">
  13. {{ selectValueText || '请选择分类' }}
  14. <uni-icons type="arrowdown" size="14" color="#999" style="margin-left: 4px;" />
  15. </view>
  16. </picker>
  17. <uni-search-bar
  18. class="my-search-bar"
  19. @confirm="onSearch"
  20. @focus="onFocus"
  21. @blur="onBlur"
  22. @clear="onClear"
  23. @cancel="onCancel"
  24. @input="onInput"
  25. cancelButton="none"
  26. bgColor="#f7f7f7"
  27. v-model="value"
  28. placeholder="请输入搜索内容"
  29. >
  30. <uni-icons slot="clearIcon" type="clear" color="#999999" />
  31. </uni-search-bar>
  32. </view>
  33. <view class="search-btn-container" @click="onSearch">
  34. <button class="search-btn" type="primary">搜索</button>
  35. </view>
  36. <view class="filter-container">
  37. <view class="total-reslut" v-if="listData.length > 0">
  38. 搜索到 {{ total }} 条记录 {{ totalPage }} 当前第 {{ page }}
  39. </view>
  40. <!-- <view>筛选</view> -->
  41. </view>
  42. </view>
  43. <view style="padding-top: 154px;" v-if="listData.length > 0">
  44. <scroll-view
  45. scroll-y
  46. style="height: calc(100vh - 80px);"
  47. @scrolltolower="onScrollLower"
  48. >
  49. <book-list-item
  50. class="hot-list-item"
  51. v-for="(item, index) in listData"
  52. :key="index"
  53. :data="item"
  54. :ranking="index + 1"
  55. @click="onItemClick(item)"
  56. ></book-list-item>
  57. <view class="load-more" v-if="total > listData.length">
  58. 上拉加载更多...
  59. </view>
  60. <view class="load-more" v-if="total <= listData.length && listData.length > 0">
  61. 没有更多数据了
  62. </view>
  63. </scroll-view>
  64. </view>
  65. <!-- 空状态 -->
  66. <view class="empty-box" v-if="isSearched && listData.length === 0">
  67. <text>没有检索到相关数据</text>
  68. </view>
  69. </view>
  70. </template>
  71. <script>
  72. import { FetchInitScreenSetting } from '@/api/user';
  73. import { FetchBookSearch } from '@/api/book';
  74. import BookListItem from "@/components/book-list-item/book-list-item.vue";
  75. export default {
  76. components: { BookListItem },
  77. data() {
  78. return {
  79. selectValue: '',
  80. selectValueText: '',
  81. selectIndex: 0,
  82. value: '',
  83. range: [
  84. // { value: '', text: "任意词" },
  85. { value: 'title', text: "题名" },
  86. { value: 'title200a', text: "正题名" },
  87. { value: 'author', text: "著者" },
  88. { value: 'isbn', text: "ISBN" },
  89. { value: 'subject', text: "主题" },
  90. { value: 'publisher', text: "出版社" },
  91. { value: 'class', text: "分类号" },
  92. { value: 'ctrlno', text: "控制号" },
  93. { value: 'orderno', text: "订购号" },
  94. { value: 'callno', text: "索书号" },
  95. ],
  96. rangeText: [],
  97. opacUrl: '',
  98. listData: [],
  99. size: 10,
  100. page: 1,
  101. total: 0,
  102. totalPage: 0,
  103. isSearched: false
  104. };
  105. },
  106. onLoad() {
  107. this.rangeText = this.range.map(item => item.text);
  108. this.selectValue = this.range[0].value;
  109. this.selectValueText = this.range[0].text;
  110. this.getOpacUrl();
  111. },
  112. methods: {
  113. // 获取opacUrl
  114. async getOpacUrl() {
  115. try {
  116. const res = await FetchInitScreenSetting({ libcode: '1201' });
  117. this.opacUrl = res.data.opac_url?.context || '';
  118. } catch (err) {
  119. console.error('获取配置失败', err);
  120. }
  121. },
  122. // 切换检索类型
  123. onPickerChange(e) {
  124. const index = e.detail.value;
  125. this.selectIndex = index;
  126. this.selectValue = this.range[index].value;
  127. this.selectValueText = this.range[index].text;
  128. },
  129. async getBookList() {
  130. if (!this.value) {
  131. uni.showToast({ title: '请输入搜索内容', icon: 'none' });
  132. return;
  133. }
  134. if (!this.opacUrl) {
  135. uni.showToast({ title: '未获取到检索配置', icon: 'none' });
  136. return;
  137. }
  138. uni.showLoading({ title: '搜索中...' });
  139. try {
  140. const params = {
  141. opacUrl: this.opacUrl,
  142. page: this.page.toString(),
  143. query: this.value,
  144. rows: this.size.toString(),
  145. scWay: 'dim',
  146. searchWay: this.selectValue,
  147. sortOrder: 'desc',
  148. sortWay: 'score'
  149. };
  150. const res = await FetchBookSearch(params);
  151. console.log('res',res)
  152. // 精准适配你当前返回格式
  153. const apiData = res.data || {};
  154. const list = apiData.bookList || [];
  155. // 赋值总数、总页数
  156. this.total = apiData.totalCount || 0;
  157. this.totalPage = Math.ceil(this.total / this.size);
  158. // 分页拼接列表
  159. if (this.page === 1) {
  160. this.listData = list;
  161. } else {
  162. this.listData = [...this.listData, ...list];
  163. }
  164. this.isSearched = true;
  165. } catch (err) {
  166. console.error('搜索接口异常', err);
  167. this.listData = [];
  168. this.isSearched = true;
  169. } finally {
  170. uni.hideLoading();
  171. }
  172. },
  173. // 上拉加载
  174. onScrollLower() {
  175. if (this.listData.length >= this.total) return;
  176. this.page++;
  177. this.getBookList();
  178. },
  179. // 搜索
  180. onSearch() {
  181. this.page = 1;
  182. this.listData = [];
  183. this.getBookList();
  184. },
  185. // 进入详情
  186. onItemClick(item) {
  187. uni.navigateTo({
  188. url: "/subpkg/pages/book-detail/book-detail?bookrecno=" + item.bookrecno
  189. })
  190. },
  191. // 清空搜索
  192. onClear() {
  193. this.value = '';
  194. this.listData = [];
  195. this.total = 0;
  196. this.totalPage = 0;
  197. this.isSearched = false;
  198. },
  199. onFocus() {},
  200. onBlur() {},
  201. onCancel() {},
  202. onInput(val) { this.value = val; }
  203. }
  204. };
  205. </script>
  206. <style lang="scss" scoped>
  207. .my-search-container {
  208. display: flex;
  209. flex-direction: column;
  210. padding: 15px 20px;
  211. background: #fff;
  212. position: fixed;
  213. top: 0;
  214. left: 0;
  215. right: 0;
  216. z-index: 99;
  217. height: 124px;
  218. .my-search-wrapper {
  219. display: flex;
  220. align-items: center;
  221. width: 100%;
  222. padding: 5px 0;
  223. background-color: #f7f7f7;
  224. border-radius: 36px;
  225. overflow: hidden;
  226. }
  227. .picker-select {
  228. width: 60px;
  229. border-right: 1px solid #c9c9c9;
  230. }
  231. .picker-display {
  232. display: flex;
  233. align-items: center;
  234. justify-content: center;
  235. padding: 6px 0;
  236. font-size: 14px;
  237. color: #333;
  238. }
  239. .my-search-bar {
  240. flex: 1;
  241. ::v-deep .uni-searchbar {
  242. padding: 0 !important;
  243. background: transparent !important;
  244. }
  245. }
  246. .search-btn-container {
  247. width: 100%;
  248. margin-top: 10px;
  249. .search-btn {
  250. background-color: #01a4fe;
  251. font-size: 15px;
  252. border-radius: 20px;
  253. }
  254. }
  255. }
  256. .filter-container {
  257. display: flex;
  258. justify-content: flex-end;
  259. padding-top: 10px;
  260. font-size: 13px;
  261. color: #666;
  262. }
  263. .load-more {
  264. text-align: center;
  265. padding: 10px;
  266. font-size: 13px;
  267. color: #999;
  268. }
  269. .total-reslut {
  270. flex: 1;
  271. line-height: 20px;
  272. font-size: 13px;
  273. color: #01a4fe;
  274. font-weight: 400;
  275. }
  276. .empty-box {
  277. display: flex;
  278. justify-content: center;
  279. align-items: center;
  280. height: 50vh;
  281. font-size: 14px;
  282. color: #999;
  283. padding-top: 100px;
  284. }
  285. </style>