飞天云平台-国产化
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.
 
 
 
 

220 lines
8.3 KiB

<template>
<div>
<div class="config-item-main">
<span class="data-title">图书推荐</span>
<div class="upload-item">
<p>推荐列表</p>
<div class="book-swiper-wrapper">
<swiper
ref="bookSwiper"
:options="swiperOptions"
class="book-swiper"
>
<swiper-slide
v-for="(book, index) in bookList"
:key="book.id"
class="book-list-item"
:class="{ 'book-list-item--selected': book.selected }"
style="background-color: transparent;"
>
<div style="cursor: default;" @click.stop="toggleBookSelect(index)">
<img :src="book.imgPath ? (baseApi + '/api/fileRelevant/getImg?imgType=2&imgId=' + book.imgPath) : require('@/assets/images/screen/book.png')" alt="图书封面">
<div v-if="book.selected" class="select-style">
<div class="select-mask" />
<i class="iconfont icon-wancheng" style="font-size: 20px; right: 6px; top: 6px;" />
</div>
</div>
<!-- <span style="position: absolute; top: 0; left: 0; color: #fff;">{{ book.id }}</span> -->
<!-- <div style="position: relative; position: absolute; left: 0; bottom: 0; width: calc(100% - 15px); display: flex; justify-content: space-between; padding: 0 5px 0 10px; background: rgba(0,0,0,.5); cursor: pointer;">
<div class="book-select" @click.stop="toggleBookSelect(index)">
<i v-if="book.selected" class="iconfont icon-wancheng" />
<i v-else class="iconfont icon-weixuan" />
</div>
<div class="book-delete" @click.stop="deleteBook(book)">
<i class="iconfont icon-shanchu" />
</div>
</div> -->
</swiper-slide>
</swiper>
</div>
<!-- <div class="book-upload-btn" @click.stop="uploadBook"><i class="iconfont icon-shangchuan2" /></div> -->
</div>
<div style="display: flex; flex-direction: column; justify-content: flex-start;">
<el-button size="mini" type="primary" @click.stop="uploadBook"><i class="iconfont icon-shangchuan" />图书上传</el-button>
<el-button :loading="deleteLoading" size="mini" style="margin-left: 0 !important; margin-top: 10px;" :disabled="!hasSelectedItems" @click="batchDelete">
<i class="iconfont icon-shanchu" />
批量删除
</el-button>
</div>
<addBookDialog ref="addBookRef" @refresh="updateBookItem" />
</div>
<div class="config-remarks" style="margin-top: 20px;">推荐图书数量大于等于20本,显示效果最佳!当前已上传数量<span style="color: #0c0e1e; font-weight: bold;"> {{ bookList.length }}</span> 本<span v-if="bookList.length<20" style="color: #ed4a41; padding-left: 10px;">未达到展示的最佳效果</span></div>
</div>
</template>
<script>
import { FetchInitScreenBookRecommend, FetchDeleteScreenBookRecommend } from '@/api/digitalScreen/index'
import { swiper, swiperSlide } from 'vue-awesome-swiper'
import 'swiper/dist/css/swiper.css'
import addBookDialog from './addBookDialog'
import { mapGetters } from 'vuex'
// import { getCurrentTime } from '@/utils/index'
// import { upload } from '@/utils/upload'
export default {
name: 'BookRecommend',
components: {
swiper,
swiperSlide,
addBookDialog
},
data() {
return {
deleteLoading: false,
bookList: [],
swiperOptions: {
slidesPerView: 'auto', // 保持自动适应数量
freeMode: true, // 自由滑动模式
// 关键:添加间距配置(匹配 slide 的左右 margin 总和 5+5=10px)
spaceBetween: 10,
// 优化自由滑动动量,确保能滑到最末端
freeModeMomentum: true, // 启用动量滑动
freeModeMomentumRatio: 0.6, // 动量衰减比例(值越大滑动越远)
freeModeMomentumVelocityRatio: 1.2, // 动量速度比例
freeModeSticky: true, // 滑动结束时自动吸附到最近的项(增强稳定性)
// 关键:在最后一个 slide 后添加 20px 缓冲空间,避免被容器遮挡
slidesOffsetAfter: 20,
grabCursor: true,
on: {
resize: function() {
this.update()
}
}
}
}
},
computed: {
...mapGetters([
'baseApi',
'user'
]),
hasSelectedItems() {
return this.bookList.some(book => book.selected)
}
},
created() {
},
mounted() {
this.$emit('ready')
},
methods: {
initScreenBookRecommend() {
const param = {
'libcode': this.user.fonds.fondsNo
}
FetchInitScreenBookRecommend(param).then((res) => {
console.log('BookRecommend', res)
const newRes = res.map(item => ({
...item,
selected: false
}))
this.bookList = newRes
}).catch(err => {
console.log(err)
})
},
updateBookSwiper() {
if (this.$refs.bookSwiper && this.$refs.bookSwiper.swiper) {
const swiper = this.$refs.bookSwiper.swiper
swiper.update() // 重新计算尺寸和位置
swiper.slideTo(swiper.activeIndex, 0) // 重置当前位置(避免偏移)
setTimeout(() => {
swiper.update()
}, 0)
}
},
// 图书推荐
toggleBookSelect(index) {
this.bookList[index].selected = !this.bookList[index].selected
},
uploadBook() {
this.$refs.addBookRef.addBookDialogVisible = true
},
updateBookItem() {
this.initScreenBookRecommend()
this.$nextTick(() => {
this.$refs.bookSwiper.swiper.update()
this.$refs.bookSwiper.swiper.slideTo(0, 300)
})
},
batchDelete() {
const selectedCount = this.bookList.filter(book => book.selected).length
if (selectedCount === 0) return
this.deleteLoading = true
this.$confirm(`确定要删除选中的 ${selectedCount} 本图书吗?`, '提示', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning'
}).then(() => {
const ids = []
const selectedBooks = this.bookList.filter(book => book.selected)
selectedBooks.forEach(book => {
ids.push(book.id)
})
FetchDeleteScreenBookRecommend(ids).then((res) => {
console.log('res', res)
if (res.code !== 500) {
this.$message({ message: `已成功删除 ${selectedCount} 本图书`, type: 'success', offset: 8 })
this.$nextTick(() => {
this.$refs.bookSwiper.swiper.update()
})
this.initScreenBookRecommend()
} else {
this.$message({ message: '删除失败', type: 'error', offset: 8 })
}
this.deleteLoading = false
}).catch(err => {
console.log(err)
this.deleteLoading = false
})
// this.bookList = this.bookList.filter(book => !book.selected)
// this.$message.success(`已成功删除 ${selectedCount} 本图书`)
}).catch(() => {
this.deleteLoading = false
})
},
deleteBook(data) {
this.$confirm('确定要删除这本图书吗?', '提示', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning',
dangerouslyUseHTMLString: true
}).then(() => {
const ids = []
ids.push(data.id)
FetchDeleteScreenBookRecommend(ids).then((res) => {
console.log('res', res)
if (res.code !== 500) {
this.$message({ message: '删除成功', type: 'success', offset: 8 })
this.$nextTick(() => {
this.$refs.bookSwiper.swiper.update()
})
this.initScreenBookRecommend()
} else {
this.$message({ message: '删除失败', type: 'error', offset: 8 })
}
}).catch(err => {
console.log(err)
})
}).catch(() => {
// 取消删除不做处理
})
}
}
}
</script>
<style lang="scss" scoped>
@import "~@/assets/styles/digitalScreen.scss";
</style>