Browse Source

收藏图书

master
xuhuajiao 1 month ago
parent
commit
6451894988
  1. 49
      api/book.js
  2. 3
      pages/home/home.vue
  3. 47
      pages/search/search.vue
  4. 31
      subpkg/pages/activity-detail/activity-detail.vue
  5. 77
      subpkg/pages/book-detail/book-detail.vue
  6. 219
      subpkg/pages/collect-list/collect-list.vue

49
api/book.js

@ -93,3 +93,52 @@ export function FetchBookRanking(data) {
// 累计借出 // 累计借出
// /api/screenSetting/sync82 // /api/screenSetting/sync82
// 根据用户openID获取收藏图书
// ?libcode=ftzn&openId=11&page=1&size=10&title=11
export function FetchFindAllBookCollectionByOpenId(data) {
return request({
url: '/api/weixin/findAllBookCollectionByOpenId',
data
})
}
//
// 收藏图书
//{
// "author": "string",
// "bookrecno": "string",
// "booktype": "string",
// "classno": "string",
// "isbn": "string",
// "libcode": "string",
// "openid": "string",
// "page": "string",
// "price": "string",
// "pubdate": "string",
// "publisher": "string",
// "subject": "string",
// "title": "string"
// }
export function FetchCollectionBook(data) {
return request({
url: '/api/weixin/collectionBook',
method: 'POST',
data
})
}
// 取消收藏
// {
// "id": 0
// }
export function FetchCancelCollectionBook(data) {
return request({
url: '/api/weixin/cancelCollectionBook',
method: 'POST',
data
})
}

3
pages/home/home.vue

@ -114,7 +114,8 @@
:circular="false" :circular="false"
> >
<swiper-item v-for="item in readerCardList" :key="item.id"> <swiper-item v-for="item in readerCardList" :key="item.id">
<view class="card-item" :class="{'active': item.bindDefault}" @click.stop="showQrcode(item.bindValue)">
<!-- :class="{'active': item.bindDefault}" -->
<view class="card-item" @click.stop="showQrcode(item.bindValue)">
<image class="card-left-img" src="@/static/images/card-img2.png" mode="widthFix" /> <image class="card-left-img" src="@/static/images/card-img2.png" mode="widthFix" />
<view class="card-right-info"> <view class="card-right-info">
<text class="info-title">读者证号</text> <text class="info-title">读者证号</text>

47
pages/search/search.vue

@ -77,9 +77,10 @@
<script> <script>
import { FetchInitScreenSetting } from '@/api/user'; import { FetchInitScreenSetting } from '@/api/user';
import { FetchBookSearch } from '@/api/book';
import { FetchBookSearch, FetchFindAllBookCollectionByOpenId } from '@/api/book';
import BookListItem from "@/components/book-list-item/book-list-item.vue"; import BookListItem from "@/components/book-list-item/book-list-item.vue";
import config from '@/utils/config'; import config from '@/utils/config';
import { getOpenId } from '@/utils/storage';
export default { export default {
components: { BookListItem }, components: { BookListItem },
@ -194,7 +195,7 @@ export default {
} }
this.isSearched = true; this.isSearched = true;
console.log('this.listData',this.listData)
} catch (err) { } catch (err) {
console.error('搜索接口异常', err); console.error('搜索接口异常', err);
this.listData = []; this.listData = [];
@ -218,10 +219,46 @@ export default {
}, },
// //
onItemClick(item) {
async onItemClick(item) {
console.log('item', item);
let isCollected = false;
let collectId = null;
try {
const openId = await getOpenId();
if (openId) {
const res = await FetchFindAllBookCollectionByOpenId({
libcode: config.LIB_CODE,
openId: openId,
page: 0,
size: 100
});
if (res.code === 200) {
const collectList = res.data.content || [];
const bookrecno = String(item.bookrecno);
//
const matchedItem = collectList.find(collectItem => String(collectItem.bookrecno) === bookrecno);
if (matchedItem) {
isCollected = true;
collectId = matchedItem.id; // id
}
}
}
} catch (err) {
console.error('获取收藏列表失败', err);
}
//
const itemWithCollectInfo = {
...item,
id: collectId // id
};
console.log('itemWithCollectInfo',itemWithCollectInfo)
const isCollectedParam = isCollected ? '&isCollected=true' : '';
uni.navigateTo({ uni.navigateTo({
url: "/subpkg/pages/book-detail/book-detail?bookrecno=" + item.bookrecno
})
url: "/subpkg/pages/book-detail/book-detail?searchData=" + encodeURIComponent(JSON.stringify(itemWithCollectInfo)) + isCollectedParam
});
}, },
// //

31
subpkg/pages/activity-detail/activity-detail.vue

@ -45,7 +45,6 @@ export default {
data() { data() {
return { return {
detail: {}, detail: {},
isCollected: false,
activityId: "", activityId: "",
contentNodes: "" contentNodes: ""
}; };
@ -55,22 +54,11 @@ export default {
this.detail = item; this.detail = item;
this.activityId = item.title; this.activityId = item.title;
this.formatContent(); this.formatContent();
this.checkCollectStatus();
}, },
methods: { methods: {
formatContent() { formatContent() {
let content = this.detail.content || ""; let content = this.detail.content || "";
// const localImgReg = /<image[^>]*\s+src\s*=\s*['"]@\/static\/([^'"]+)['"][^>]*>/gi;
// content = content.replace(localImgReg, (match, path) => {
// return `
// <div style="text-align:center; margin:12px 0;">
// <img src="/static/${path}" style="width:90%; border-radius:8px;">
// </div>
// `;
// });
const httpImgReg = /https:\/\/mmbiz\.qpic\.cn[^ \n\r'"]+/g; const httpImgReg = /https:\/\/mmbiz\.qpic\.cn[^ \n\r'"]+/g;
content = content.replace(httpImgReg, url => { content = content.replace(httpImgReg, url => {
return ` return `
@ -82,25 +70,6 @@ export default {
this.contentNodes = content; this.contentNodes = content;
}, },
checkCollectStatus() {
const list = uni.getStorageSync('activityCollectList') || [];
this.isCollected = list.includes(this.activityId);
},
toggleCollect() {
let list = uni.getStorageSync('activityCollectList') || [];
if (this.isCollected) {
list = list.filter(i => i !== this.activityId);
uni.showToast({ title: "取消收藏" });
} else {
list.push(this.activityId);
uni.showToast({ title: "收藏成功", icon: "success" });
}
uni.setStorageSync('activityCollectList', list);
this.isCollected = !this.isCollected;
},
handleJoin() { handleJoin() {
if (this.detail.status === 0) { if (this.detail.status === 0) {
return; return;

77
subpkg/pages/book-detail/book-detail.vue

@ -96,7 +96,8 @@
<script> <script>
import { FetchInitScreenSetting } from '@/api/user'; import { FetchInitScreenSetting } from '@/api/user';
import { FetchFindbookByQuery, FetchDictionaryTree } from '@/api/book';
import { FetchFindbookByQuery, FetchDictionaryTree,FetchCollectionBook,FetchCancelCollectionBook } from '@/api/book';
import { getOpenId } from '@/utils/storage';
import config from '@/utils/config'; import config from '@/utils/config';
export default { export default {
@ -109,6 +110,7 @@ export default {
opacUrl: '', opacUrl: '',
fromRecommend: false, fromRecommend: false,
bookInfo: {}, bookInfo: {},
searchListInfo: {},
holdingsData: [], holdingsData: [],
dictionaryTree: {}, dictionaryTree: {},
libraryMap: {}, libraryMap: {},
@ -126,9 +128,19 @@ export default {
this.checkCollectStatus(); this.checkCollectStatus();
return; return;
} }
console.log('options',options)
// 2. bookrecno // 2. bookrecno
this.bookrecno = options.bookrecno || "";
if(options.searchData){
const bookData = JSON.parse(decodeURIComponent(options.searchData));
this.searchListInfo = bookData;
this.bookrecno = bookData.bookrecno || "";
}
// 3.
if (options.isCollected === 'true') {
this.isCollected = true;
}
this.fromRecommend = false; this.fromRecommend = false;
this.getOpacUrl(); this.getOpacUrl();
this.getDictionaryTree(); this.getDictionaryTree();
@ -194,7 +206,7 @@ export default {
} catch (err) {} } catch (err) {}
}, },
//
//
async getBookDetail() { async getBookDetail() {
if (!this.bookrecno || !this.opacUrl) return; if (!this.bookrecno || !this.opacUrl) return;
@ -251,25 +263,66 @@ export default {
return this.locationMap[orglocal] || orglocal || '葛店图书馆'; return this.locationMap[orglocal] || orglocal || '葛店图书馆';
}, },
//
//
checkCollectStatus() { checkCollectStatus() {
if (this.isCollected) return;
const list = uni.getStorageSync('collectList') || []; const list = uni.getStorageSync('collectList') || [];
this.isCollected = list.includes(this.bookrecno); this.isCollected = list.includes(this.bookrecno);
}, },
toggleCollect() {
let list = uni.getStorageSync('collectList') || [];
async toggleCollect() {
const openId = await getOpenId();
if (!openId) {
uni.showToast({ title: '获取用户信息失败', icon: 'none' });
return;
}
if (this.isCollected) { if (this.isCollected) {
list = list.filter(i => i !== this.bookrecno);
try {
console.log(' this.searchListInfo.id',this.searchListInfo.id);
const res = await FetchCancelCollectionBook({id: this.searchListInfo.id});
if (res.code === 200) {
this.isCollected = false;
// id
if (this.searchListInfo) {
this.searchListInfo.id = null;
}
//
uni.setStorageSync('needRefreshCollect', true);
uni.showToast({ title: '取消收藏', icon: 'success' }); uni.showToast({ title: '取消收藏', icon: 'success' });
} else { } else {
list.push(this.bookrecno);
uni.showToast({ title: res.message || '取消收藏失败', icon: 'none' });
}
} catch (err) {
console.error('取消收藏图书失败', err);
uni.showToast({ title: '取消收藏失败', icon: 'none' });
}
} else {
try {
const params = {
...this.searchListInfo,
openid: openId,
libcode: config.LIB_CODE
};
const res = await FetchCollectionBook(params);
if (res.code === 200) {
this.isCollected = true;
// id使
if (res.data && res.data.id) {
this.searchListInfo.id = res.data.id;
}
uni.showToast({ title: '收藏成功', icon: 'success' }); uni.showToast({ title: '收藏成功', icon: 'success' });
} else {
uni.showToast({ title: res.message || '收藏失败', icon: 'none' });
}
} catch (err) {
console.error('收藏图书失败', err);
uni.showToast({ title: '收藏失败', icon: 'none' });
}
} }
uni.setStorageSync('collectList', list);
this.isCollected = !this.isCollected;
} }
}, },
onShareAppMessage() { onShareAppMessage() {
return { return {
title: this.bookInfo.title || '图书详情', title: this.bookInfo.title || '图书详情',

219
subpkg/pages/collect-list/collect-list.vue

@ -1,22 +1,21 @@
<template> <template>
<view class="collection-page"> <view class="collection-page">
<view class="content-box"> <view class="content-box">
<view class="empty" v-if="bookCollectList.length === 0">
<view class="empty" v-if="bookCollectList.length === 0 && !isLoading">
<uni-icons style="margin-left: 20px;" custom-prefix="iconfont" type="icon-kongshuju" size="80"></uni-icons> <uni-icons style="margin-left: 20px;" custom-prefix="iconfont" type="icon-kongshuju" size="80"></uni-icons>
<text style="margin-top: 20px;">暂无收藏的图书~</text> <text style="margin-top: 20px;">暂无收藏的图书~</text>
</view> </view>
<view class="recommendation-list" v-else> <view class="recommendation-list" v-else>
<view
class="book-item"
<book-list-item
class="hot-list-item"
v-for="(item, index) in bookCollectList" v-for="(item, index) in bookCollectList"
@click="goToBookDetail(item)"
:key="index" :key="index"
>
<image class="book-cover" :src="item.cover"></image>
<view class="book-title">{{ item.title }}</view>
:data="item"
:ranking="index + 1"
@click="onItemClick(item)"
></book-list-item>
</view> </view>
</view>
<uni-load-more status="loading" v-if="isLoading"></uni-load-more>
<uni-load-more status="loading" v-if="isLoading && bookCollectList.length > 0"></uni-load-more>
<view class="no-more" v-if="noMore && bookCollectList.length > 0"> <view class="no-more" v-if="noMore && bookCollectList.length > 0">
没有更多数据了 没有更多数据了
</view> </view>
@ -25,61 +24,143 @@
</template> </template>
<script> <script>
import BookListItem from "@/components/book-list-item/book-list-item.vue";
import { FetchFindAllBookCollectionByOpenId } from '@/api/book';
import { getOpenId } from '@/utils/storage';
import config from '@/utils/config';
export default { export default {
components: {
BookListItem,
},
data() { data() {
return { return {
isLoading: false, isLoading: false,
noMore: false, noMore: false,
pageNum: 1,
pageSize: 5,
bookCollectList: [
{ isbn: '9787544741110', title: '人工智能基础——数学知识', cover: 'https://qiniu.aiyxlib.com/1606124577077' },
{ isbn: '9787539938032', title: 'Vim 8文本处理实战', cover: 'https://qiniu.aiyxlib.com/1606178450151' },
{ isbn: '9787536692930', title: 'Oracle从入门到精通', cover: 'https://qiniu.aiyxlib.com/1606123986028' }
],
pageNum: 0,
pageSize: 10,
bookCollectList: [],
hasLoadedAll: false,
} }
}, },
onLoad() { onLoad() {
// this.loadData();
}, },
onShow() {
//
const needRefresh = uni.getStorageSync('needRefreshCollect');
uni.removeStorageSync('needRefreshCollect');
//
if (this.hasLoadedAll || needRefresh) {
this.refreshData();
} else if (this.bookCollectList.length === 0) {
//
this.refreshData();
}
},
onPullDownRefresh() { onPullDownRefresh() {
this.refreshData()
this.refreshData();
}, },
onReachBottom() { onReachBottom() {
if (this.noMore || this.isLoading) return
this.loadMore()
if (this.noMore || this.isLoading) return;
this.loadMore();
}, },
methods: { methods: {
refreshData() {
this.isLoading = true
setTimeout(() => {
this.bookCollectList = [
{ isbn: '9787544741110', title: '人工智能基础——数学知识', cover: 'https://qiniu.aiyxlib.com/1606124577077' },
{ isbn: '9787539938032', title: 'Vim 8文本处理实战', cover: 'https://qiniu.aiyxlib.com/1606178450151' },
{ isbn: '9787536692930', title: 'Oracle从入门到精通', cover: 'https://qiniu.aiyxlib.com/1606123986028' }
]
this.isLoading = false
uni.stopPullDownRefresh()
}, 500)
},
async loadData() {
this.isLoading = true;
try {
const openId = await getOpenId();
if (!openId) {
uni.showToast({ title: '获取用户信息失败', icon: 'none' });
this.isLoading = false;
return;
}
const res = await FetchFindAllBookCollectionByOpenId({
libcode: config.LIB_CODE,
openId: openId,
page: this.pageNum,
size: this.pageSize,
});
loadMore() {
this.isLoading = true
this.pageNum++
setTimeout(() => {
this.noMore = true
this.isLoading = false
}, 500)
if (res.code === 200) {
this.bookCollectList = res.data.content || [];
this.noMore = (res.data.content || []).length < this.pageSize;
this.hasLoadedAll = this.noMore;
} else {
uni.showToast({ title: res.message || '获取收藏列表失败', icon: 'none' });
}
} catch (err) {
console.error('获取收藏列表失败', err);
uni.showToast({ title: '获取收藏列表失败', icon: 'none' });
} finally {
this.isLoading = false;
}
}, },
goToBookDetail(item) {
uni.navigateTo({ url: "/subpkg/pages/book-detail/book-detail?isbn=" + item.isbn })
async refreshData() {
this.pageNum = 0;
this.noMore = false;
this.bookCollectList = [];
await this.loadData();
//
uni.pageScrollTo({
scrollTop: 0,
duration: 300
});
uni.stopPullDownRefresh();
}, },
async loadMore() {
if (this.noMore || this.isLoading) return;
this.pageNum++;
this.isLoading = true;
try {
const openId = await getOpenId();
if (!openId) {
uni.showToast({ title: '获取用户信息失败', icon: 'none' });
this.isLoading = false;
return;
}
const res = await FetchFindAllBookCollectionByOpenId({
libcode: config.LIB_CODE,
openId: openId,
page: this.pageNum,
size: this.pageSize,
});
console.log('res',res)
console.log('res.data',res.data)
console.log('res.data.content',res.data.content)
if (res.code === 200) {
const newData = res.data.content || [];
this.bookCollectList = [...this.bookCollectList, ...newData];
this.noMore = newData.length < this.pageSize;
} else {
this.pageNum--;
uni.showToast({ title: res.message || '加载更多失败', icon: 'none' });
}
} catch (err) {
console.error('加载更多收藏失败', err);
this.pageNum--;
uni.showToast({ title: '加载更多失败', icon: 'none' });
} finally {
this.isLoading = false;
}
}, },
onItemClick(item) {
console.log('item',item)
uni.navigateTo({
url: "/subpkg/pages/book-detail/book-detail?searchData=" + encodeURIComponent(JSON.stringify(item)) + '&isCollected=true'
})
}
}
} }
</script> </script>
@ -96,7 +177,10 @@ export default {
.empty { .empty {
padding: 60px 0; padding: 60px 0;
text-align: center;
color: #999;
} }
.no-more { .no-more {
text-align: center; text-align: center;
padding: 20px 0; padding: 20px 0;
@ -105,9 +189,56 @@ export default {
} }
.recommendation-list { .recommendation-list {
flex-wrap: wrap;
display: flex;
flex-direction: column;
gap: 12px;
}
.book-item { .book-item {
margin-bottom: 16px;
display: flex;
background: #fff;
border-radius: 8px;
padding: 12px;
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.06);
}
.book-cover {
width: 80px;
height: 100px;
border-radius: 4px;
flex-shrink: 0;
background: #f5f5f5;
} }
.book-info {
flex: 1;
display: flex;
flex-direction: column;
justify-content: center;
padding-left: 12px;
overflow: hidden;
}
.book-title {
font-size: 15px;
font-weight: 500;
color: #333;
line-height: 1.4;
display: -webkit-box;
-webkit-box-orient: vertical;
-webkit-line-clamp: 2;
overflow: hidden;
}
.book-author {
font-size: 13px;
color: #999;
margin-top: 6px;
}
.book-publisher {
font-size: 12px;
color: #ccc;
margin-top: 4px;
} }
</style> </style>
Loading…
Cancel
Save