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

228 lines
6.1 KiB

<template>
<view class="item-container">
<view class="count-text">
<text>图书数量 ({{ bookList.length }})</text>
</view>
<!-- 购物车式列表 不用 checkbox-group-->
<view class="car-list" v-for="item in bookList" :key="item.barcode">
<checkbox :checked="item.checked" @click="toggleItem(item)" />
<view class="book-item-box">
<view class="item-box-left">
<image class="img-item" :src="defaultCover" mode="aspectFill" />
</view>
<view class="item-box-right">
<view class="item-title line-clamp-2">{{ item.title || '暂无标题' }}</view>
<view class="tag-box">
<text class="item-author">{{ item.author || '佚名' }}</text>
</view>
<view class="item-desc">应还时间:{{ item.returndate || '暂无' }}</view>
</view>
</view>
</view>
<view class="bottom-placeholder"></view>
<view class="car-bottom">
<!-- 全选 -->
<view class="all-check" @click="toggleAllCheck">
<checkbox :checked="isAllChecked" />
<text style="margin-left:6px">全选</text>
</view>
<button class="join-btn" @click="handleRenew" :disabled="!hasChecked">
一键续借
</button>
</view>
</view>
</template>
<script>
import { FetchInitScreenSetting } from '@/api/user';
import { FetchRdloanlist, FetchRenewbook } from '@/api/book';
export default {
data() {
return {
bookList: [],
defaultCover: '/static/images/default-book.png',
screenConfig: {},
};
},
onLoad() {
this.getConfigAndList();
},
computed: {
// 全选状态
isAllChecked() {
return this.bookList.length > 0 && this.bookList.every(item => item.checked);
},
// 是否有选中
hasChecked() {
return this.bookList.some(item => item.checked);
}
},
methods: {
async getConfigAndList() {
try {
const res = await FetchInitScreenSetting({ libcode: '1201' });
this.screenConfig = {
thirdUrl: res.data.open_lib_http?.context || '',
thirdAppid: res.data.open_lib_appId?.context || '',
thirdSecret: res.data.open_lib_secret?.context || '',
sm4Key: res.data.sm4_key?.context || '',
opuser: res.data.op_user?.context || 'JH001',
};
this.getLendingList();
} catch (err) {}
},
async getLendingList() {
try {
const params = {
...this.screenConfig,
rdid: uni.getStorageSync('currentReaderCard'),
};
const res = await FetchRdloanlist(params);
const result = typeof res.data === 'string' ? JSON.parse(res.data) : res.data;
// 每条数据加 checked: false 购物车选中状态
this.bookList = (result.loanlist || []).map(item => ({
...item,
checked: false
}));
} catch (err) {
uni.showToast({ title: '加载失败', icon: 'none' });
}
},
// 单个勾选(购物车逻辑)
toggleItem(item) {
item.checked = !item.checked;
},
// 全选/取消全选
toggleAllCheck() {
const isAll = this.isAllChecked;
this.bookList.forEach(item => {
item.checked = !isAll;
});
},
// 一键续借
async handleRenew() {
const checkedBooks = this.bookList.filter(item => item.checked);
if (checkedBooks.length === 0) {
uni.showToast({ title: '请选择图书', icon: 'none' });
return;
}
const barcodes = checkedBooks.map(item => item.barcode).join('|');
uni.showLoading({ title: '续借中...' });
try {
const params = {
...this.screenConfig,
rdid: uni.getStorageSync('currentReaderCard'),
barcode: barcodes,
logtype: '30007'
};
const res = await FetchRenewbook(params);
// 解析接口返回的 data 字符串
const result = typeof res.data === 'string' ? JSON.parse(res.data) : res.data;
uni.hideLoading();
if (result.success === true) {
// 续借成功
uni.showToast({
title: `续借成功!`,
icon: 'success'
});
// 刷新列表
this.getLendingList();
} else {
// 续借失败 → 取后台提示信息
let msg = '续借失败';
if (result.messagelist && result.messagelist.length > 0) {
msg = result.messagelist[0].message;
}
uni.showToast({
title: msg,
icon: 'none',
duration: 3000
});
}
} catch (err) {
uni.hideLoading();
uni.showToast({ title: '网络异常,续借失败', icon: 'none' });
console.error('续借异常:', err);
}
},
}
};
</script>
<style lang="scss" scoped>
.item-container {
padding: 10px;
background: #f5f6f7;
min-height: 100vh;
}
.count-text {
margin-bottom: 10px;
font-size: 14px;
color: #333;
}
.car-list {
display: flex;
align-items: flex-start;
margin-bottom: 10px;
checkbox {
margin-top: 15px;
padding: 0 10px;
}
}
.book-item-box {
flex: 1;
background: #fff;
border-radius: 8px;
padding: 12px;
display: flex;
.item-box-left {
margin-right: 12px;
.img-item {
width: 64px;
height: 90px;
border-radius: 6px;
}
}
.item-box-right { flex: 1; }
.item-title { font-weight: bold; margin-bottom: 4px; }
.item-author {
font-size: 12px; background: #f4f6fc;
padding: 2px 6px; border-radius: 4px; margin-right: 6px;
}
.item-desc { font-size: 12px; color: #999; margin-top: 6px; }
}
.bottom-placeholder { height: 60px; }
.car-bottom {
position: fixed; left: 0; bottom: 0; right: 0;
background: #fff; padding: 12px 15px;
display: flex; justify-content: space-between; align-items: center;
box-shadow: 0 -2px 5px rgba(0,0,0,0.05);
}
.all-check { display: flex; align-items: center; }
.join-btn {
font-size: 14px; color: #fff;
background: #01a4fe !important; border-radius: 23px;
padding: 0 30px;
&::after{ border: none !important; }
&[disabled] { background: #ccc !important; }
}
</style>