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

335 lines
9.2 KiB

<template>
<view class="lending-container">
<view class="tab-sticky">
<my-tabs
:tabData="tabData"
:defaultIndex="currentIndex"
:config="{ textColor: '#333' }"
@tabClick="tabClick"
/>
</view>
<swiper
class="swiper"
:current="currentIndex"
:style="{ height: currentSwiperHeight + 'px' }"
@animationfinish="onSwiperEnd"
@change="onSwiperChange"
>
<swiper-item v-for="(tabItem, idx) in tabData" :key="idx">
<view class="list-wrapper">
<!-- 首次加载 -->
<uni-load-more status="loading" v-if="loadingMap[tabItem.status]" />
<!-- 空数据 -->
<view class="empty" v-else-if="!listData[tabItem.status] || listData[tabItem.status].length === 0">
暂无{{ tabItem.label }}记录
</view>
<!-- 列表 -->
<block v-else>
<lending-list-item
:class="'list-item-' + tabItem.status"
v-for="(item, index) in listData[tabItem.status]"
:key="index"
:data="item"
:ranking="index + 1"
/>
</block>
<!-- 上拉加载更多 -->
<uni-load-more
v-if="listData[tabItem.status] && listData[tabItem.status].length > 0 && !loadingMap[tabItem.status]"
:status="loadMoreStatusMap[tabItem.status]"
/>
</view>
</swiper-item>
</swiper>
</view>
</template>
<script>
import { FetchInitScreenSetting } from '@/api/user';
import { FetchHistoryloan, FetchRdloanlist } from '@/api/book';
import myTabs from "@/components/my-tabs/my-tabs.vue";
import lendingListItem from "@/components/lending-list-item/lending-list-item.vue";
export default {
components: { myTabs, lendingListItem },
data() {
return {
screenConfig: {},
tabData: [
{ label: "全部", status: "all", apiStatus: -1 },
{ label: "在借中", status: "lending", apiStatus: 0 },
// { label: "将过期", status: "expiring", apiStatus: 1 },
// { label: "已过期", status: "expired", apiStatus: 2 },
],
currentIndex: 0,
listData: {},
loadingMap: {},
loadMoreStatusMap: {},
pageMap: {},
sizeMap: {},
hasMoreMap: {},
swiperHeightData: {},
currentSwiperHeight: 400,
currentPageScrollTop: 0,
isRefreshing: false
};
},
onLoad() {
this.getScreenSetting();
this.initDataStructure();
},
onShow() {
const tabIndex = uni.getStorageSync('switch_tab_index');
if (tabIndex !== undefined && tabIndex !== '') {
this.currentIndex = Number(tabIndex);
uni.removeStorageSync('switch_tab_index');
}
},
onPullDownRefresh() {
this.isRefreshing = true;
const currentTab = this.getCurrentTab();
this.refreshList(currentTab.status);
},
onReachBottom() {
const currentTab = this.getCurrentTab();
this.loadMoreList(currentTab.status);
},
onPageScroll(res) {
this.currentPageScrollTop = res.scrollTop;
},
methods: {
async getScreenSetting() {
try {
const res = await FetchInitScreenSetting({ libcode: '1201' });
const data = res.data;
this.screenConfig = {
thirdUrl: data.open_lib_http?.context || '',
thirdAppid: data.open_lib_appId?.context || '',
thirdSecret: data.open_lib_secret?.context || '',
sm4Key: data.sm4_key?.context || ''
};
} catch (err) {
console.error('获取配置失败:', err);
}
},
// 获取 在借中 列表(字段已对齐)
async getRealBorrowList(statusKey) {
this.loadingMap[statusKey] = true;
try {
const rdid = uni.getStorageSync('currentReaderCard');
const params = { ...this.screenConfig, rdid };
const res = await FetchRdloanlist(params);
const result = typeof res.data === 'string' ? JSON.parse(res.data) : res.data;
let loanList = result.loanlist || [];
// 对齐字段:loandate → loantime,returndate → returntime
loanList = loanList.map(item => {
const loantime = item.loandate || '';
const returntime = item.returndate || '';
const now = new Date();
const returnDate = new Date(returntime);
const diffDay = Math.ceil((returnDate - now) / (1000 * 3600 * 24));
let returnBook = 0;
if (diffDay < 0) {
returnBook = 3;
} else if (diffDay <= 3) {
returnBook = 1;
} else {
returnBook = 0;
}
return {
...item,
loantime,
returntime,
startTime: loantime,
returnTime: returntime,
returnBook
};
});
console.log('当前借阅', loanList);
this.listData['lending'] = loanList;
this.listData['expiring'] = loanList.filter(i => i.returnBook === 1);
this.listData['expired'] = loanList.filter(i => i.returnBook === 3);
this.hasMoreMap[statusKey] = false;
this.loadMoreStatusMap[statusKey] = "no-more";
} catch (err) {
console.error('获取在借列表失败', err);
this.listData[statusKey] = [];
} finally {
this.loadingMap[statusKey] = false;
this.isRefreshing = false;
uni.stopPullDownRefresh();
setTimeout(() => this.calcSwiperHeight(statusKey), 0);
}
},
// 获取 全部/历史 列表
async getHistoryList(statusKey) {
this.loadingMap[statusKey] = true;
try {
const rdid = uni.getStorageSync('currentReaderCard');
const params = { ...this.screenConfig, rdid, logtype:'30002' };
const res = await FetchHistoryloan(params);
const result = typeof res.data === 'string' ? JSON.parse(res.data) : res.data;
let loanList = result.hloanlist || [];
loanList = loanList.map(item => {
return {
...item,
returnTime: item.returntime || '',
startTime: item.loantime || item.optime || '',
returnBook: 2
};
});
console.log('历史借阅', loanList);
this.listData[statusKey] = loanList;
this.hasMoreMap[statusKey] = false;
this.loadMoreStatusMap[statusKey] = "no-more";
} catch (err) {
console.error('获取历史列表失败', err);
this.listData[statusKey] = [];
} finally {
this.loadingMap[statusKey] = false;
this.isRefreshing = false;
uni.stopPullDownRefresh();
setTimeout(() => this.calcSwiperHeight(statusKey), 0);
}
},
initDataStructure() {
this.tabData.forEach(tab => {
const key = tab.status;
this.$set(this.listData, key, []);
this.$set(this.loadingMap, key, true);
this.$set(this.loadMoreStatusMap, key, "");
this.$set(this.pageMap, key, 1);
this.$set(this.sizeMap, key, 10);
this.$set(this.hasMoreMap, key, true);
});
},
getCurrentTab() {
return this.tabData[this.currentIndex];
},
async getListData(statusKey) {
if (statusKey === 'all') {
await this.getHistoryList(statusKey);
}
if (statusKey === 'lending') {
await this.getRealBorrowList(statusKey);
}
if (statusKey === 'expiring' || statusKey === 'expired') {
await this.getRealBorrowList('lending');
this.loadingMap[statusKey] = false;
}
},
loadMoreList(statusKey) {
this.loadMoreStatusMap[statusKey] = "no-more";
},
refreshList(statusKey) {
this.getListData(statusKey);
},
calcSwiperHeight(statusKey) {
const selector = `.list-item-${statusKey}`;
const query = uni.createSelectorQuery().in(this);
query.selectAll(selector).boundingClientRect((res) => {
let total = 200;
if (res?.length) {
total = res.reduce((t, h) => t + h.height + 8, 0);
}
this.swiperHeightData[statusKey] = total;
this.currentSwiperHeight = total;
}).exec();
},
tabClick(index) {
this.currentIndex = index;
const tab = this.getCurrentTab();
if (this.currentPageScrollTop > 100) {
uni.pageScrollTo({ scrollTop: 0, duration: 100 });
}
this.getListData(tab.status);
},
onSwiperChange(e) {
if (e.detail.source === "touch") {
this.currentIndex = e.detail.current;
}
},
onSwiperEnd() {
const tab = this.getCurrentTab();
this.getListData(tab.status);
},
goToDetail(item) {
uni.navigateTo({
url: `/subpkg/pages/book-detail/book-detail?isbn=${item.isbn}`
});
}
}
};
</script>
<style lang="scss" scoped>
.lending-container {
background-color: #f5f5f5;
min-height: 100vh;
.tab-sticky {
position: sticky;
top: 0;
z-index: 99;
background: #fff;
}
.swiper {
width: 100%;
min-height: 300px;
}
.swiper-item {
width: 100%;
height: 100%;
}
.list-wrapper {
padding: 10px;
box-sizing: border-box;
}
.empty {
text-align: center;
padding: 100px 0;
color: #999;
font-size: 14px;
}
}
::v-deep .uni-load-more{
height: auto !important;
}
</style>