-
31library-activity/README.md
-
52library-activity/src/assets/css/style.scss
-
BINlibrary-activity/src/assets/images/active-img.png
-
BINlibrary-activity/src/assets/images/empty.png
-
62library-activity/src/components/aitoast/aitoast.vue
-
477library-activity/src/components/verify/slide-verify.vue
-
6library-activity/src/router/index.js
-
59library-activity/src/views/activeDetail/activeDetail.vue
-
22library-activity/src/views/bookList/bookList.vue
-
359library-activity/src/views/cart/cart copy.vue
-
112library-activity/src/views/cart/cart.vue
-
4library-activity/src/views/feedback/feedback.vue
-
13library-activity/src/views/index.vue
-
21library-activity/src/views/logisticsInfo/logisticsInfo.vue
-
15library-activity/src/views/mine/mine.vue
-
6library-activity/src/views/myAddress/addAddress.vue
-
8library-activity/src/views/myAddress/myAddress.vue
-
78library-activity/src/views/myLending/myLending.vue
-
16library-activity/src/views/orderDetail/orderDetail.vue
-
12selfServiceMachine/README.md
-
2selfServiceMachine/public/index.html
-
BINselfServiceMachine/public/logo.png
-
BINselfServiceMachine/src/assets/logo.png
-
26selfServiceMachine/src/assets/styles/index.scss
-
127selfServiceMachine/src/views/bookRecommend.vue
-
222selfServiceMachine/src/views/module/bookDetails.vue
-
134selfServiceMachine/src/views/module/bookList.vue
-
51selfServiceMachine/src/views/module/headerTop.vue
-
97selfServiceMachine/src/views/module/homeListItem.vue
After Width: 750 | Height: 1624 | Size: 576 KiB |
After Width: 335 | Height: 236 | Size: 11 KiB |
@ -1,62 +0,0 @@ |
|||||
<template> |
|
||||
<div class="tishi-di" v-if="data.ifs"> |
|
||||
<div class="tishi"> |
|
||||
{{toastmassage}} |
|
||||
</div> |
|
||||
</div> |
|
||||
</template> |
|
||||
|
|
||||
<script> |
|
||||
import { reactive,computed,onMounted,watch } from 'vue'; |
|
||||
export default { |
|
||||
props: { |
|
||||
toastmassage: { |
|
||||
type: String, |
|
||||
default: '' |
|
||||
}, |
|
||||
iftshow: { |
|
||||
type: Number, |
|
||||
default: 0 |
|
||||
} |
|
||||
}, |
|
||||
setup(props){ |
|
||||
const data = reactive({ |
|
||||
timer:null, |
|
||||
ifs:false |
|
||||
}) |
|
||||
watch(() => props.iftshow, (oldVlaue, newValue) => { |
|
||||
data.ifs = true; |
|
||||
}) |
|
||||
watch(() => data.ifs, (oldVlaue, newValue) => { |
|
||||
let that = data; |
|
||||
clearTimeout(that.timer); |
|
||||
that.timer = null; |
|
||||
that.timer=setTimeout(function(){ |
|
||||
that.ifs = false; |
|
||||
},1500) |
|
||||
}) |
|
||||
return { |
|
||||
data |
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
</script> |
|
||||
|
|
||||
<style> |
|
||||
.tishi-di{ |
|
||||
width: 100%; |
|
||||
position: fixed; |
|
||||
bottom: 16%; |
|
||||
left: 0; |
|
||||
display: flex; |
|
||||
justify-content: center; |
|
||||
align-items: center; |
|
||||
} |
|
||||
.tishi{ |
|
||||
padding: 0.18rem 0.40rem; |
|
||||
background-color: rgb(226,226,226,0.9); |
|
||||
font-size: 0.28rem; |
|
||||
color: #222222; |
|
||||
border-radius: 0.04rem; |
|
||||
} |
|
||||
</style> |
|
@ -1,477 +0,0 @@ |
|||||
<template> |
|
||||
<div class="slide-verify" :style="{width: w + 'px'}" id="slideVerify" onselectstart="return false;"> |
|
||||
<!-- 图片加载遮蔽罩 --> |
|
||||
<div :class="{'slider-verify-loading': loadBlock}"></div> |
|
||||
<canvas :width="w" :height="h" ref="canvas" ></canvas> |
|
||||
<div v-if="show" @click="refresh" class="slide-verify-refresh-icon"></div> |
|
||||
<canvas :width="w" :height="h" ref="block" class="slide-verify-block"></canvas> |
|
||||
<!-- container --> |
|
||||
<div class="slide-verify-slider" :class="{'container-active': containerActive, 'container-success': containerSuccess, 'container-fail': containerFail}"> |
|
||||
<div class="slide-verify-slider-mask" :style="{width: sliderMaskWidth}"> |
|
||||
<!-- slider --> |
|
||||
<div @mousedown="sliderDown" |
|
||||
@touchstart="touchStartEvent" |
|
||||
@touchmove="touchMoveEvent" |
|
||||
@touchend="touchEndEvent" |
|
||||
class="slide-verify-slider-mask-item" |
|
||||
:style="{left: sliderLeft}"> |
|
||||
<div class="slide-verify-slider-mask-item-icon"></div> |
|
||||
</div> |
|
||||
</div> |
|
||||
<span class="slide-verify-slider-text">{{sliderText}}</span> |
|
||||
</div> |
|
||||
</div> |
|
||||
</template> |
|
||||
<script> |
|
||||
const PI = Math.PI; |
|
||||
|
|
||||
function sum(x, y) { |
|
||||
return x + y |
|
||||
} |
|
||||
|
|
||||
function square(x) { |
|
||||
return x * x |
|
||||
} |
|
||||
export default { |
|
||||
name: 'SlideVerify', |
|
||||
props: { |
|
||||
// block length |
|
||||
l: { |
|
||||
type: Number, |
|
||||
default: 42, |
|
||||
}, |
|
||||
// block radius |
|
||||
r: { |
|
||||
type: Number, |
|
||||
default: 10, |
|
||||
}, |
|
||||
// canvas width |
|
||||
w: { |
|
||||
type: Number, |
|
||||
default: 310, |
|
||||
}, |
|
||||
// canvas height |
|
||||
h: { |
|
||||
type: Number, |
|
||||
default: 155, |
|
||||
}, |
|
||||
sliderText: { |
|
||||
type: String, |
|
||||
default: '向右滑动滑块填充拼图', |
|
||||
}, |
|
||||
accuracy: { |
|
||||
type: Number, |
|
||||
default: 5, // 若为 -1 则不进行机器判断 |
|
||||
}, |
|
||||
show: { |
|
||||
type: Boolean, |
|
||||
default: true, |
|
||||
}, |
|
||||
imgs: { |
|
||||
type: Array, |
|
||||
default: () => [], |
|
||||
}, |
|
||||
}, |
|
||||
data() { |
|
||||
return { |
|
||||
containerActive: false, // container active class |
|
||||
containerSuccess: false, // container success class |
|
||||
containerFail: false, // container fail class |
|
||||
canvasCtx: null, |
|
||||
blockCtx: null, |
|
||||
block: null, |
|
||||
block_x: undefined, // container random position |
|
||||
block_y: undefined, |
|
||||
L: this.l + this.r * 2 + 3, // block real lenght |
|
||||
img: undefined, |
|
||||
originX: undefined, |
|
||||
originY: undefined, |
|
||||
isMouseDown: false, |
|
||||
trail: [], |
|
||||
sliderLeft: 0, // block right offset |
|
||||
sliderMaskWidth: 0, // mask width, |
|
||||
success: false, // Bug Fixes 修复了验证成功后还能滑动 |
|
||||
loadBlock: true, // Features 图片加载提示,防止图片没加载完就开始验证 |
|
||||
timestamp: null, |
|
||||
} |
|
||||
}, |
|
||||
mounted() { |
|
||||
this.init() |
|
||||
}, |
|
||||
methods: { |
|
||||
init() { |
|
||||
this.initDom() |
|
||||
this.initImg() |
|
||||
this.bindEvents() |
|
||||
}, |
|
||||
initDom() { |
|
||||
this.block = this.$refs.block; |
|
||||
this.canvasCtx = this.$refs.canvas.getContext('2d') |
|
||||
this.blockCtx = this.block.getContext('2d') |
|
||||
}, |
|
||||
initImg() { |
|
||||
const img = this.createImg(() => { |
|
||||
// 图片加载完关闭遮蔽罩 |
|
||||
this.loadBlock = false; |
|
||||
this.drawBlock() |
|
||||
this.canvasCtx.drawImage(img, 0, 0, this.w, this.h) |
|
||||
this.blockCtx.drawImage(img, 0, 0, this.w, this.h) |
|
||||
let { |
|
||||
block_x: x, |
|
||||
block_y: y, |
|
||||
r, |
|
||||
L |
|
||||
} = this |
|
||||
let _y = y - r * 2 - 1 |
|
||||
let ImageData = this.blockCtx.getImageData(x, _y, L, L); |
|
||||
this.block.width = L; |
|
||||
this.blockCtx.putImageData(ImageData, 0, _y) |
|
||||
}); |
|
||||
this.img = img; |
|
||||
}, |
|
||||
drawBlock() { |
|
||||
this.block_x = this.getRandomNumberByRange(this.L + 10, this.w - (this.L + 10)) |
|
||||
this.block_y = this.getRandomNumberByRange(10 + this.r * 2, this.h - (this.L + 10)) |
|
||||
this.draw(this.canvasCtx, this.block_x, this.block_y, 'fill') |
|
||||
this.draw(this.blockCtx, this.block_x, this.block_y, 'clip') |
|
||||
}, |
|
||||
draw(ctx, x, y, operation) { |
|
||||
let { |
|
||||
l, |
|
||||
r |
|
||||
} = this; |
|
||||
ctx.beginPath() |
|
||||
ctx.moveTo(x, y) |
|
||||
ctx.arc(x + l / 2, y - r + 2, r, 0.72 * PI, 2.26 * PI) |
|
||||
ctx.lineTo(x + l, y) |
|
||||
ctx.arc(x + l + r - 2, y + l / 2, r, 1.21 * PI, 2.78 * PI) |
|
||||
ctx.lineTo(x + l, y + l) |
|
||||
ctx.lineTo(x, y + l) |
|
||||
ctx.arc(x + r - 2, y + l / 2, r + 0.4, 2.76 * PI, 1.24 * PI, true) |
|
||||
ctx.lineTo(x, y) |
|
||||
ctx.lineWidth = 2 |
|
||||
ctx.fillStyle = 'rgba(255, 255, 255, 0.7)' |
|
||||
ctx.strokeStyle = 'rgba(255, 255, 255, 0.7)' |
|
||||
ctx.stroke() |
|
||||
ctx[operation]() |
|
||||
// Bug Fixes 修复了火狐和ie显示问题 |
|
||||
ctx.globalCompositeOperation = "destination-over" |
|
||||
}, |
|
||||
createImg(onload) { |
|
||||
const img = document.createElement('img'); |
|
||||
img.crossOrigin = "Anonymous"; |
|
||||
img.onload = onload; |
|
||||
img.onerror = () => { |
|
||||
img.src = this.getRandomImg() |
|
||||
} |
|
||||
img.src = this.getRandomImg() |
|
||||
return img; |
|
||||
}, |
|
||||
// 随机生成img src |
|
||||
getRandomImg() { |
|
||||
// return require('../assets/img.jpg') |
|
||||
const len = this.imgs.length; |
|
||||
return len > 0 ? |
|
||||
this.imgs[this.getRandomNumberByRange(0, len)] : |
|
||||
'https://picsum.photos/300/150/?image=' + this.getRandomNumberByRange(0, 1084); |
|
||||
}, |
|
||||
getRandomNumberByRange(start, end) { |
|
||||
return Math.round(Math.random() * (end - start) + start) |
|
||||
}, |
|
||||
refresh() { |
|
||||
this.reset() |
|
||||
this.$emit('refresh') |
|
||||
}, |
|
||||
sliderDown(event) { |
|
||||
if (this.success) return; |
|
||||
this.originX = event.clientX; |
|
||||
this.originY = event.clientY; |
|
||||
this.isMouseDown = true; |
|
||||
this.timestamp = + new Date(); |
|
||||
}, |
|
||||
touchStartEvent(e) { |
|
||||
if (this.success) return; |
|
||||
this.originX = e.changedTouches[0].pageX; |
|
||||
this.originY = e.changedTouches[0].pageY; |
|
||||
this.isMouseDown = true; |
|
||||
this.timestamp = + new Date(); |
|
||||
}, |
|
||||
bindEvents() { |
|
||||
document.addEventListener('mousemove', (e) => { |
|
||||
if (!this.isMouseDown) return false; |
|
||||
const moveX = e.clientX - this.originX; |
|
||||
const moveY = e.clientY - this.originY; |
|
||||
if (moveX < 0 || moveX + 38 >= this.w) return false; |
|
||||
this.sliderLeft = moveX + 'px'; |
|
||||
let blockLeft = (this.w - 40 - 20) / (this.w - 40) * moveX; |
|
||||
this.block.style.left = blockLeft + 'px'; |
|
||||
|
|
||||
this.containerActive = true; // add active |
|
||||
this.sliderMaskWidth = moveX + 'px'; |
|
||||
this.trail.push(moveY); |
|
||||
}); |
|
||||
document.addEventListener('mouseup', (e) => { |
|
||||
if (!this.isMouseDown) return false |
|
||||
this.isMouseDown = false |
|
||||
if (e.clientX === this.originX) return false; |
|
||||
this.containerActive = false; // remove active |
|
||||
this.timestamp = + new Date() - this.timestamp; |
|
||||
|
|
||||
const { |
|
||||
spliced, |
|
||||
TuringTest |
|
||||
} = this.verify(); |
|
||||
if (spliced) { |
|
||||
if(this.accuracy === -1) { |
|
||||
this.containerSuccess = true; |
|
||||
this.success = true; |
|
||||
this.$emit('success', this.timestamp); |
|
||||
return; |
|
||||
} |
|
||||
if (TuringTest) { |
|
||||
// succ |
|
||||
this.containerSuccess = true; |
|
||||
this.success = true; |
|
||||
this.$emit('success', this.timestamp) |
|
||||
} else { |
|
||||
this.containerFail = true; |
|
||||
this.$emit('again') |
|
||||
} |
|
||||
} else { |
|
||||
this.containerFail = true; |
|
||||
this.$emit('fail') |
|
||||
setTimeout(() => { |
|
||||
this.reset() |
|
||||
}, 1000) |
|
||||
} |
|
||||
}) |
|
||||
}, |
|
||||
touchMoveEvent(e) { |
|
||||
if (!this.isMouseDown) return false; |
|
||||
const moveX = e.changedTouches[0].pageX - this.originX; |
|
||||
const moveY = e.changedTouches[0].pageY - this.originY; |
|
||||
if (moveX < 0 || moveX + 38 >= this.w) return false; |
|
||||
this.sliderLeft = moveX + 'px'; |
|
||||
let blockLeft = (this.w - 40 - 20) / (this.w - 40) * moveX; |
|
||||
this.block.style.left = blockLeft + 'px'; |
|
||||
|
|
||||
this.containerActive = true; |
|
||||
this.sliderMaskWidth = moveX + 'px'; |
|
||||
this.trail.push(moveY); |
|
||||
}, |
|
||||
touchEndEvent(e) { |
|
||||
if (!this.isMouseDown) return false |
|
||||
this.isMouseDown = false |
|
||||
if (e.changedTouches[0].pageX === this.originX) return false; |
|
||||
this.containerActive = false; |
|
||||
this.timestamp = + new Date() - this.timestamp; |
|
||||
|
|
||||
const { |
|
||||
spliced, |
|
||||
TuringTest |
|
||||
} = this.verify(); |
|
||||
if (spliced) { |
|
||||
if(this.accuracy === -1) { |
|
||||
this.containerSuccess = true; |
|
||||
this.success = true; |
|
||||
this.$emit('success', this.timestamp); |
|
||||
return; |
|
||||
} |
|
||||
if (TuringTest) { |
|
||||
// succ |
|
||||
this.containerSuccess = true; |
|
||||
this.success = true; |
|
||||
this.$emit('success', this.timestamp) |
|
||||
} else { |
|
||||
this.containerFail = true; |
|
||||
this.$emit('again') |
|
||||
} |
|
||||
} else { |
|
||||
this.containerFail = true; |
|
||||
this.$emit('fail') |
|
||||
setTimeout(() => { |
|
||||
this.reset() |
|
||||
}, 1000) |
|
||||
} |
|
||||
}, |
|
||||
verify() { |
|
||||
const arr = this.trail // drag y move distance |
|
||||
const average = arr.reduce(sum) / arr.length // average |
|
||||
const deviations = arr.map(x => x - average) // deviation array |
|
||||
const stddev = Math.sqrt(deviations.map(square).reduce(sum) / arr.length) // standard deviation |
|
||||
const left = parseInt(this.block.style.left) |
|
||||
const accuracy = this.accuracy <= 1 ? 1 : this.accuracy > 10 ? 10 : this.accuracy; |
|
||||
return { |
|
||||
spliced: Math.abs(left - this.block_x) <= accuracy, |
|
||||
TuringTest: average !== stddev, // equal => not person operate |
|
||||
} |
|
||||
}, |
|
||||
reset() { |
|
||||
this.success = false; |
|
||||
this.containerActive = false; |
|
||||
this.containerSuccess = false; |
|
||||
this.containerFail = false; |
|
||||
this.sliderLeft = 0; |
|
||||
this.block.style.left = 0; |
|
||||
this.sliderMaskWidth = 0; |
|
||||
// canvas |
|
||||
let { |
|
||||
w, |
|
||||
h |
|
||||
} = this; |
|
||||
this.canvasCtx.clearRect(0, 0, w, h) |
|
||||
this.blockCtx.clearRect(0, 0, w, h) |
|
||||
this.block.width = w |
|
||||
|
|
||||
// generate img |
|
||||
this.img.src = this.getRandomImg(); |
|
||||
this.$emit('fulfilled') |
|
||||
}, |
|
||||
} |
|
||||
} |
|
||||
</script> |
|
||||
<style scoped> |
|
||||
.slide-verify { |
|
||||
position: relative; |
|
||||
} |
|
||||
|
|
||||
/* 图片加载样式 */ |
|
||||
.slider-verify-loading{ |
|
||||
position: absolute; |
|
||||
top: 0; |
|
||||
right: 0; |
|
||||
left: 0; |
|
||||
bottom: 0; |
|
||||
background: rgba(255, 255, 255, 0.9); |
|
||||
z-index: 999; |
|
||||
animation: loading 1.5s infinite; |
|
||||
} |
|
||||
|
|
||||
@keyframes loading { |
|
||||
0%{ |
|
||||
opacity: .7; |
|
||||
} |
|
||||
100% { |
|
||||
opacity: 9; |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
.slide-verify-block { |
|
||||
position: absolute; |
|
||||
left: 0; |
|
||||
top: 0 |
|
||||
} |
|
||||
|
|
||||
.slide-verify-refresh-icon { |
|
||||
position: absolute; |
|
||||
right: 0; |
|
||||
top: 0; |
|
||||
width: 34px; |
|
||||
height: 34px; |
|
||||
cursor: pointer; |
|
||||
background: url("../../assets/images/login/icon_light.png") 0 -437px; |
|
||||
background-size: 34px 471px |
|
||||
} |
|
||||
|
|
||||
.slide-verify-slider { |
|
||||
position: relative; |
|
||||
text-align: center; |
|
||||
width: 100%; |
|
||||
height: 40px; |
|
||||
line-height: 40px; |
|
||||
margin-top: 15px; |
|
||||
background: #f7f9fa; |
|
||||
color: #45494c; |
|
||||
border: 1px solid #e4e7eb |
|
||||
} |
|
||||
|
|
||||
.slide-verify-slider-mask { |
|
||||
position: absolute; |
|
||||
left: 0; |
|
||||
top: 0; |
|
||||
height: 40px; |
|
||||
border: 0 solid #1991FA; |
|
||||
background: #D1E9FE |
|
||||
} |
|
||||
|
|
||||
.slide-verify-slider-mask-item { |
|
||||
position: absolute; |
|
||||
top: 0; |
|
||||
left: 0; |
|
||||
width: 40px; |
|
||||
height: 40px; |
|
||||
background: #fff; |
|
||||
box-shadow: 0 0 3px rgba(0, 0, 0, 0.3); |
|
||||
cursor: pointer; |
|
||||
transition: background .2s linear |
|
||||
} |
|
||||
|
|
||||
.slide-verify-slider-mask-item:hover { |
|
||||
background: #1991FA |
|
||||
} |
|
||||
|
|
||||
.slide-verify-slider-mask-item:hover .slide-verify-slider-mask-item-icon { |
|
||||
background-position: 0 -13px |
|
||||
} |
|
||||
|
|
||||
.slide-verify-slider-mask-item-icon { |
|
||||
position: absolute; |
|
||||
top: 15px; |
|
||||
left: 13px; |
|
||||
width: 14px; |
|
||||
height: 12px; |
|
||||
background: url("../../assets/images/login/icon_light.png") 0 -26px; |
|
||||
background-size: 34px 471px |
|
||||
} |
|
||||
.container-active .slide-verify-slider-mask-item { |
|
||||
height: 38px; |
|
||||
top: -1px; |
|
||||
border: 1px solid #1991FA; |
|
||||
} |
|
||||
|
|
||||
.container-active .slide-verify-slider-mask { |
|
||||
height: 38px; |
|
||||
border-width: 1px; |
|
||||
} |
|
||||
|
|
||||
.container-success .slide-verify-slider-mask-item { |
|
||||
height: 38px; |
|
||||
top: -1px; |
|
||||
border: 1px solid #52CCBA; |
|
||||
background-color: #52CCBA !important; |
|
||||
} |
|
||||
|
|
||||
.container-success .slide-verify-slider-mask { |
|
||||
height: 38px; |
|
||||
border: 1px solid #52CCBA; |
|
||||
background-color: #D2F4EF; |
|
||||
} |
|
||||
|
|
||||
.container-success .slide-verify-slider-mask-item-icon { |
|
||||
background-position: 0 0 !important; |
|
||||
} |
|
||||
|
|
||||
.container-fail .slide-verify-slider-mask-item { |
|
||||
height: 38px; |
|
||||
top: -1px; |
|
||||
border: 1px solid #f57a7a; |
|
||||
background-color: #f57a7a !important; |
|
||||
} |
|
||||
|
|
||||
.container-fail .slide-verify-slider-mask { |
|
||||
height: 38px; |
|
||||
border: 1px solid #f57a7a; |
|
||||
background-color: #fce1e1; |
|
||||
} |
|
||||
|
|
||||
.container-fail .slide-verify-slider-mask-item-icon { |
|
||||
top: 14px; |
|
||||
background-position: 0 -82px !important; |
|
||||
} |
|
||||
|
|
||||
.container-active .slide-verify-slider-text, |
|
||||
.container-success .slide-verify-slider-text, |
|
||||
.container-fail .slide-verify-slider-text { |
|
||||
display: none; |
|
||||
} |
|
||||
</style> |
|
@ -0,0 +1,59 @@ |
|||||
|
<template> |
||||
|
<div class="main"> |
||||
|
<div class="active-detail"> |
||||
|
<img src="@assets/images/active-img.png" alt="" /> |
||||
|
<span @click="toBookList">开始选书</span> |
||||
|
</div> |
||||
|
</div> |
||||
|
</template> |
||||
|
|
||||
|
<script> |
||||
|
import { reactive, onMounted, getCurrentInstance,toRefs } from 'vue' |
||||
|
|
||||
|
export default { |
||||
|
name:'ActiveDetail', |
||||
|
setup() { |
||||
|
const { proxy } = getCurrentInstance() |
||||
|
const data = reactive({ |
||||
|
}) |
||||
|
onMounted(async () => { |
||||
|
}) |
||||
|
let toBookList = () => { |
||||
|
proxy.$router.push({ path: '/BookList' }) |
||||
|
} |
||||
|
return { |
||||
|
...toRefs(data), |
||||
|
toBookList |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
</script> |
||||
|
|
||||
|
<style lang="scss" scoped> |
||||
|
.active-detail{ |
||||
|
img{ |
||||
|
display: block; |
||||
|
width: 100%; |
||||
|
} |
||||
|
span{ |
||||
|
position: fixed; |
||||
|
bottom: .45rem; |
||||
|
left: 50%; |
||||
|
transform: translateX(-50%); |
||||
|
display: block; |
||||
|
width: 3.07rem; |
||||
|
height: .8rem; |
||||
|
line-height: .8rem; |
||||
|
font-size: .3rem; |
||||
|
font-weight: bold; |
||||
|
text-align: center; |
||||
|
background: linear-gradient(135deg, #48FCD4 0%, #01FFB9 99%); |
||||
|
box-shadow: 0px 0px .16rem 0px #636EBA; |
||||
|
border-radius: .4rem; |
||||
|
} |
||||
|
// width: 100%; |
||||
|
// height: 100vh; |
||||
|
// background: url('@assets/images/active-img.png') no-repeat; |
||||
|
// background-size: cover; |
||||
|
} |
||||
|
</style> |
@ -1,359 +0,0 @@ |
|||||
<template> |
|
||||
<div class="main"> |
|
||||
<div class="cart-main"> |
|
||||
<div class="cart-top"> |
|
||||
<div class="cart-num">图书数量<span>(5)</span></div> |
|
||||
<span @click="cartDelt">管理</span> |
|
||||
</div> |
|
||||
<div class="cart-list"> |
|
||||
<div class="cart-item"> |
|
||||
<div class="list-top"> |
|
||||
<van-checkbox v-model="checked"></van-checkbox> |
|
||||
<div class="top-info"> |
|
||||
<p class="active-name">你选书,我买单<i></i></p> |
|
||||
<p class="dealer">京东商城</p> |
|
||||
</div> |
|
||||
</div> |
|
||||
<div class="product-list"> |
|
||||
<div class="product-item"> |
|
||||
<van-checkbox v-model="checked"></van-checkbox> |
|
||||
<div class="product-cont"> |
|
||||
<div class="product-img"><img src="" alt="" /></div> |
|
||||
<div class="product-txt"> |
|
||||
<div class="product-info"> |
|
||||
<h4 class="overflow-txt-only">秒懂AI提问:让人工智能开发大脑 </h4> |
|
||||
<div class="author-date"> |
|
||||
<p class="author overflow-txt-only">秋叶 刘进新 姜梅 定秋枫</p> |
|
||||
<p class="date overflow-txt-only ">2023年07月</p> |
|
||||
</div> |
|
||||
<div class="intro overflow-txt">精心提炼20种GPT提问方法及指令,从入门到进阶再到精通,100个案例带你玩</div> |
|
||||
</div> |
|
||||
<div class="product-bottom"> |
|
||||
<p class="product-price">实付款 <span><i class="rmb">¥</i>29.0</span><i>129.0</i></p> |
|
||||
<span class="product-num">x1</span> |
|
||||
</div> |
|
||||
</div> |
|
||||
</div> |
|
||||
</div> |
|
||||
<div class="product-item"> |
|
||||
<van-checkbox v-model="checked"></van-checkbox> |
|
||||
<div class="product-cont"> |
|
||||
<div class="product-img"><img src="" alt="" /></div> |
|
||||
<div class="product-txt"> |
|
||||
<div class="product-info"> |
|
||||
<h4 class="overflow-txt-only">秒懂AI提问:让人工智能开发大脑 </h4> |
|
||||
<div class="author-date"> |
|
||||
<p class="author overflow-txt-only">秋叶 刘进新 姜梅 定秋枫</p> |
|
||||
<p class="date overflow-txt-only ">2023年07月</p> |
|
||||
</div> |
|
||||
<div class="intro overflow-txt">精心提炼20种GPT提问方法及指令,从入门到进阶再到精通,100个案例带你玩</div> |
|
||||
</div> |
|
||||
<div class="product-bottom"> |
|
||||
<p class="product-price">实付款 <span><i class="rmb">¥</i>29.0</span><i>129.0</i></p> |
|
||||
<span class="product-num">x1</span> |
|
||||
</div> |
|
||||
</div> |
|
||||
</div> |
|
||||
</div> |
|
||||
</div> |
|
||||
</div> |
|
||||
|
|
||||
<div class="cart-item"> |
|
||||
<div class="list-top"> |
|
||||
<van-checkbox v-model="checked"></van-checkbox> |
|
||||
<div class="top-info"> |
|
||||
<p class="active-name">你选书,我买单<i></i></p> |
|
||||
<p class="dealer">京东商城</p> |
|
||||
</div> |
|
||||
</div> |
|
||||
<div class="product-list"> |
|
||||
<div class="product-item"> |
|
||||
<van-checkbox v-model="checked"></van-checkbox> |
|
||||
<div class="product-cont"> |
|
||||
<div class="product-img"><img src="" alt="" /></div> |
|
||||
<div class="product-txt"> |
|
||||
<div class="product-info"> |
|
||||
<h4 class="overflow-txt-only">秒懂AI提问:让人工智能开发大脑 </h4> |
|
||||
<div class="author-date"> |
|
||||
<p class="author overflow-txt-only">秋叶 刘进新 姜梅 定秋枫</p> |
|
||||
<p class="date overflow-txt-only ">2023年07月</p> |
|
||||
</div> |
|
||||
<div class="intro overflow-txt">精心提炼20种GPT提问方法及指令,从入门到进阶再到精通,100个案例带你玩</div> |
|
||||
</div> |
|
||||
<div class="product-bottom"> |
|
||||
<p class="product-price">实付款 <span><i class="rmb">¥</i>29.0</span><i>129.0</i></p> |
|
||||
<span class="product-num">x1</span> |
|
||||
</div> |
|
||||
</div> |
|
||||
</div> |
|
||||
</div> |
|
||||
</div> |
|
||||
</div> |
|
||||
</div> |
|
||||
</div> |
|
||||
<div class="cart-pay"> |
|
||||
<van-checkbox v-model="checked">全选</van-checkbox> |
|
||||
<div v-if="!isDeltHandle" class="payment-right"> |
|
||||
<div class="total-num">合计:<span><i class="rmb">¥</i>0</span></div> |
|
||||
<p class="pay-btn" @click="goPay">下单</p> |
|
||||
</div> |
|
||||
<div v-else class="payment-right"> |
|
||||
<p class="delt-btn" @click="confirmDelt">删除</p> |
|
||||
</div> |
|
||||
</div> |
|
||||
<TabBar :tabCur.sync="tabCur" /> |
|
||||
</div> |
|
||||
</template> |
|
||||
|
|
||||
<script> |
|
||||
import { Toast } from 'vant' |
|
||||
import { reactive, computed, onMounted, getCurrentInstance, toRefs } from 'vue' |
|
||||
import TabBar from '@/components/tabBar/index.vue' |
|
||||
export default { |
|
||||
name: 'Cart', |
|
||||
components: { TabBar }, |
|
||||
setup() { |
|
||||
const { proxy } = getCurrentInstance() |
|
||||
let data = reactive({ |
|
||||
tabCur: 1, |
|
||||
checked: false, |
|
||||
isDeltHandle: false |
|
||||
}) |
|
||||
onMounted(() => {}) |
|
||||
let goPay = () => { |
|
||||
proxy.$router.push({ path: '/CartResult' }) |
|
||||
} |
|
||||
let cartDelt = () =>{ |
|
||||
data.isDeltHandle = !data.isDeltHandle |
|
||||
} |
|
||||
return { |
|
||||
...toRefs(data), |
|
||||
goPay, |
|
||||
cartDelt |
|
||||
} |
|
||||
}, |
|
||||
} |
|
||||
</script> |
|
||||
|
|
||||
<style scoped lang="scss"> |
|
||||
.cart-main{ |
|
||||
padding: 0.25rem .125rem 2.375rem .125rem; |
|
||||
color: #191A1A; |
|
||||
.cart-top{ |
|
||||
position: fixed; |
|
||||
top: 0; |
|
||||
right: 0; |
|
||||
left: 0; |
|
||||
display: flex; |
|
||||
justify-content: space-between; |
|
||||
align-items: center; |
|
||||
font-size: .3rem; |
|
||||
padding: .25rem; |
|
||||
background-color: #F4F4FC; |
|
||||
z-index: 999; |
|
||||
.cart-num{ |
|
||||
font-size: .3rem; |
|
||||
opacity: 0.6; |
|
||||
span{ |
|
||||
font-size: 0.25rem; |
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
.cart-list{ |
|
||||
padding-top: .875rem; |
|
||||
} |
|
||||
.cart-item{ |
|
||||
padding: .25rem; |
|
||||
margin-bottom: .1875rem; |
|
||||
box-shadow: 0px .0375rem 0.75rem 1px rgba(0,0,0,0.08); |
|
||||
border-radius: 0.1rem; |
|
||||
background-color: #fff; |
|
||||
.list-top{ |
|
||||
display: flex; |
|
||||
justify-content: flex-start; |
|
||||
align-items: center; |
|
||||
.top-info{ |
|
||||
display: flex; |
|
||||
flex: 1; |
|
||||
justify-content: space-between; |
|
||||
align-items: center; |
|
||||
} |
|
||||
.active-name{ |
|
||||
position: relative; |
|
||||
padding: 0 0.375rem; |
|
||||
font-size: .3rem; |
|
||||
font-weight: bold; |
|
||||
background: url('@assets/images/gift.png') no-repeat left center; |
|
||||
background-size: 0.275rem 0.275rem; |
|
||||
&::after{ |
|
||||
position: absolute; |
|
||||
right: 0; |
|
||||
top: 50%; |
|
||||
content: ""; |
|
||||
width: .2rem; |
|
||||
height: .2rem; |
|
||||
background: url('@assets/images/arrow.png') no-repeat center center; |
|
||||
background-size:.2rem .2rem; |
|
||||
transform: translateY(-50%) |
|
||||
} |
|
||||
} |
|
||||
.dealer{ |
|
||||
padding-left: .4rem; |
|
||||
font-size: .3rem; |
|
||||
background: url('@assets/images/dealer.png') no-repeat left center; |
|
||||
background-size: .3rem .3rem; |
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
.product-list{ |
|
||||
.product-item{ |
|
||||
display: flex; |
|
||||
justify-content: flex-start; |
|
||||
margin-top: .25rem; |
|
||||
.product-cont{ |
|
||||
flex: 1; |
|
||||
display: flex; |
|
||||
justify-content: flex-start; |
|
||||
.product-img{ |
|
||||
width: 1.25rem; |
|
||||
height: 1.75rem; |
|
||||
margin: .125rem 0.2rem 0 0; |
|
||||
background-color: #f1f1f1; |
|
||||
border-radius: 0.05rem; |
|
||||
overflow: hidden; |
|
||||
} |
|
||||
.product-txt{ |
|
||||
flex: 1; |
|
||||
.product-info{ |
|
||||
h4{ |
|
||||
font-size: .3rem; |
|
||||
} |
|
||||
.author-date{ |
|
||||
display: flex; |
|
||||
justify-content: flex-start; |
|
||||
margin: .075rem 0; |
|
||||
p{ |
|
||||
font-size: .25rem; |
|
||||
padding: 0 .05rem; |
|
||||
margin-right: 0.1rem; |
|
||||
background-color: #F4F6FC; |
|
||||
color: #717275; |
|
||||
} |
|
||||
} |
|
||||
.intro{ |
|
||||
font-size: .25rem; |
|
||||
opacity: 0.6; |
|
||||
} |
|
||||
} |
|
||||
.product-bottom{ |
|
||||
display: flex; |
|
||||
justify-content: space-between; |
|
||||
align-items: center; |
|
||||
color: #757676; |
|
||||
.product-price{ |
|
||||
span{ |
|
||||
display: inline-block; |
|
||||
font-size: .35rem; |
|
||||
font-weight: bold; |
|
||||
color: #000; |
|
||||
margin-right: 0.175rem; |
|
||||
.rmb{ |
|
||||
font-style: normal; |
|
||||
font-size: .25rem; |
|
||||
text-decoration: none; |
|
||||
color: #000; |
|
||||
} |
|
||||
} |
|
||||
i{ |
|
||||
font-style: normal; |
|
||||
text-decoration: line-through; |
|
||||
color: #FF3871; |
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
.cart-pay{ |
|
||||
position: fixed; |
|
||||
left: 0; |
|
||||
right: 0; |
|
||||
bottom: 1.225rem; |
|
||||
padding: 0 .4rem; |
|
||||
height: 1rem; |
|
||||
// background-color: #fcfcfc; |
|
||||
background: linear-gradient(#fff, #f1f1f1); |
|
||||
display: flex; |
|
||||
justify-content: space-between; |
|
||||
align-items: center; |
|
||||
.payment-right{ |
|
||||
display: flex; |
|
||||
justify-content: space-between; |
|
||||
align-items: center; |
|
||||
font-size: .3rem; |
|
||||
.total-num{ |
|
||||
font-size: 0.3rem; |
|
||||
span{ |
|
||||
font-size: .35rem; |
|
||||
font-weight: bold; |
|
||||
color: #FF3871; |
|
||||
.rmb{ |
|
||||
font-style: normal; |
|
||||
font-size: .25rem; |
|
||||
text-decoration: none; |
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
.pay-btn{ |
|
||||
width: 1.875rem; |
|
||||
height: 0.75rem; |
|
||||
margin-left: 0.5rem; |
|
||||
line-height: 0.75rem; |
|
||||
text-align: center; |
|
||||
color: #fff; |
|
||||
background: url('@assets/images/btn3.png') no-repeat center center; |
|
||||
background-size: 100% 100%; |
|
||||
} |
|
||||
.delt-btn{ |
|
||||
width: 1.875rem; |
|
||||
height: 0.75rem; |
|
||||
line-height: 0.75rem; |
|
||||
font-size: .3rem; |
|
||||
color: #000; |
|
||||
text-align: center; |
|
||||
border: 2px solid #000; |
|
||||
opacity: 0.6; |
|
||||
border-radius: .625rem; |
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
.van-checkbox{ |
|
||||
margin-right: .15rem; |
|
||||
} |
|
||||
|
|
||||
:deep(.van-checkbox__icon){ |
|
||||
height: .325rem; |
|
||||
} |
|
||||
:deep(.van-checkbox__icon .van-icon){ |
|
||||
width: .325rem; |
|
||||
height: .325rem; |
|
||||
border-color: rgba(0,0,0,.3); |
|
||||
} |
|
||||
:deep(.van-checkbox__icon--checked .van-icon){ |
|
||||
border: none; |
|
||||
background: url('@assets/images/selected.png') no-repeat transparent; |
|
||||
background-size: .325rem .325rem; |
|
||||
} |
|
||||
:deep(.van-icon-success:before){ |
|
||||
display: none; |
|
||||
} |
|
||||
:deep(.van-checkbox__label){ |
|
||||
font-size: .3rem; |
|
||||
} |
|
||||
|
|
||||
</style> |
|
After Width: 40 | Height: 40 | Size: 1.1 KiB |
Before Width: 200 | Height: 200 | Size: 6.7 KiB After Width: 40 | Height: 40 | Size: 1.1 KiB |
@ -1,222 +0,0 @@ |
|||||
<template> |
|
||||
<div> |
|
||||
<el-dialog title="图书详情" :visible.sync="dialogVisible" width="80%"> |
|
||||
<!-- :before-close="handleClose" --> |
|
||||
<div class="dialog-setting"> |
|
||||
<div v-if="bookData" class="book-details-box"> |
|
||||
<div class="book-details"> |
|
||||
<div class="book-cover"> |
|
||||
<img :src="bookData.srcUrl ? bookData.srcUrl : ''" :onerror="defaultImg" /> |
|
||||
</div> |
|
||||
<div class="book-desc"> |
|
||||
<h3>{{ bookData.bookName }}</h3> |
|
||||
<p class="book-from">作者:{{ bookData.bookAuthor }}</p> |
|
||||
<p v-if="bookData.Publish" class="book-from">出版社:{{ bookData.Publish }}</p> |
|
||||
<p class="book-brief"> 简介:{{ bookData.gist ? bookData.gist : '暂无简介' }}</p> |
|
||||
</div> |
|
||||
</div> |
|
||||
<div class="book-local"> |
|
||||
<!-- <span v-if="bookData.bookPlace">所在位置:{{ bookData.bookPlace }}</span> --> |
|
||||
<!-- 待定:热门图书/新书推荐跳转到 场馆导航操作 --> |
|
||||
<!-- <span v-else>所在位置</span> --> |
|
||||
<div class="local-title"> |
|
||||
所在位置 |
|
||||
</div> |
|
||||
<ul class="local-list"> |
|
||||
<li v-if="!bookData.places[0]?.shelfName" class="local-none"> |
|
||||
<!-- <svg class="icon svg-icon" aria-hidden="true"> |
|
||||
<use xlink:href="#icon-weizhi" /> |
|
||||
</svg> --> |
|
||||
<span>当前图书暂未查到位置信息</span> |
|
||||
</li> |
|
||||
<!-- --> |
|
||||
<li v-for="(item,index) in bookData.places" v-else :key="index" class="local-list-info" @click="toBookNav(index)"> |
|
||||
<svg class="icon svg-icon" aria-hidden="true"> |
|
||||
<use xlink:href="#icon-weizhi" /> |
|
||||
</svg> |
|
||||
<span>{{ item.shelfName }}</span> |
|
||||
</li> |
|
||||
</ul> |
|
||||
</div> |
|
||||
</div> |
|
||||
</div> |
|
||||
</el-dialog> |
|
||||
</div> |
|
||||
</template> |
|
||||
|
|
||||
<script> |
|
||||
export default { |
|
||||
name: 'BookDetails', |
|
||||
data() { |
|
||||
return { |
|
||||
dialogVisible: false, |
|
||||
bookData: null, |
|
||||
defaultImg: 'this.src="' + require('@/assets/images/default-img.png') + '"' |
|
||||
} |
|
||||
}, |
|
||||
created() { |
|
||||
}, |
|
||||
methods: { |
|
||||
toBookNav(index) { |
|
||||
const linkSrc = process.env.VUE_APP_BASE_API |
|
||||
window.location.href = linkSrc + '/anchoring/goNavigation.do?libcode=' + this.libcode + '&barcode=' + this.bookData.places[index].barcode |
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
</script> |
|
||||
|
|
||||
<style lang="scss" scoped> |
|
||||
::v-deep .el-dialog { |
|
||||
position: fixed; |
|
||||
top: 50%; |
|
||||
left: 50%; |
|
||||
transform: translate(-50%, -50%); |
|
||||
border-radius: 24px; |
|
||||
margin-top: 0 !important; |
|
||||
.el-dialog__body { |
|
||||
padding: 0 40px 40px 40px; |
|
||||
} |
|
||||
} |
|
||||
::v-deep .el-dialog__header { |
|
||||
text-align: center; |
|
||||
padding-top: 0; |
|
||||
padding-bottom: 4px; |
|
||||
.el-dialog__title { |
|
||||
display: inline-block; |
|
||||
font-family: "ZhenyanGB"; |
|
||||
font-size: 40px; |
|
||||
width: 494px; |
|
||||
height: 76px; |
|
||||
line-height: 76px; |
|
||||
background: url("~@/assets/images/list/list-title.png") no-repeat 0 0; |
|
||||
} |
|
||||
} |
|
||||
::v-deep .el-dialog__headerbtn { |
|
||||
background-color: #3f92f6; |
|
||||
width: 40px; |
|
||||
height: 40px; |
|
||||
border-radius: 50%; |
|
||||
.el-dialog__close { |
|
||||
color: #fff; |
|
||||
font-size: 30px; |
|
||||
} |
|
||||
} |
|
||||
.book-details-box { |
|
||||
.book-details { |
|
||||
display: flex; |
|
||||
justify-content: space-between; |
|
||||
padding: 30px 0; |
|
||||
.book-cover { |
|
||||
display: flex; |
|
||||
align-items: center; |
|
||||
width: 318px; |
|
||||
height: 382px; |
|
||||
margin-right: 40px; |
|
||||
overflow: hidden; |
|
||||
img { |
|
||||
display: block; |
|
||||
width: 100%; |
|
||||
max-height: calc(100%); |
|
||||
object-fit: contain; |
|
||||
} |
|
||||
} |
|
||||
.book-desc { |
|
||||
flex: 1; |
|
||||
color: #333; |
|
||||
overflow: hidden; |
|
||||
h3 { |
|
||||
font-size: 40px; |
|
||||
font-weight: normal; |
|
||||
} |
|
||||
.book-from { |
|
||||
width: 100%; |
|
||||
font-size: 30px; |
|
||||
} |
|
||||
h3, |
|
||||
.book-from { |
|
||||
text-overflow: -o-ellipsis-lastline; |
|
||||
overflow: hidden; |
|
||||
text-overflow: ellipsis; |
|
||||
display: -webkit-box; |
|
||||
-webkit-line-clamp: 2; |
|
||||
line-clamp: 2; |
|
||||
-webkit-box-orient: vertical; |
|
||||
margin-bottom: 20px; |
|
||||
} |
|
||||
.book-brief { |
|
||||
font-size: 24px; |
|
||||
margin-bottom: 20px; |
|
||||
text-overflow: -o-ellipsis-lastline; |
|
||||
overflow: hidden; |
|
||||
text-overflow: ellipsis; |
|
||||
display: -webkit-box; |
|
||||
-webkit-line-clamp: 4; |
|
||||
line-clamp: 4; |
|
||||
-webkit-box-orient: vertical; |
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
.book-local { |
|
||||
height: 343px; |
|
||||
color: #333; |
|
||||
display: flex; |
|
||||
// border-radius: 52px; |
|
||||
// line-height: 64px; |
|
||||
// text-align: center; |
|
||||
// font-size: 30px; |
|
||||
// overflow: hidden; |
|
||||
// white-space: nowrap; |
|
||||
// text-overflow: ellipsis; |
|
||||
.local-title { |
|
||||
width: 83px; |
|
||||
height: 100%; |
|
||||
background: url("~@/assets/images/local-bg.png") no-repeat; |
|
||||
writing-mode: vertical-rl; |
|
||||
text-align: center; |
|
||||
line-height: 83px; |
|
||||
font-size: 30px; |
|
||||
color: #fff; |
|
||||
} |
|
||||
.local-list { |
|
||||
flex: 1; |
|
||||
border: 1px solid #3f92f6; |
|
||||
border-left: none; |
|
||||
background: #d0e0f9; |
|
||||
overflow: hidden; |
|
||||
overflow-y: auto; |
|
||||
position: relative; |
|
||||
font-size: 26px; |
|
||||
.local-list-info { |
|
||||
height: 56px; |
|
||||
line-height: 56px; |
|
||||
background-color: #fff; |
|
||||
// margin-right: 8px; |
|
||||
margin-bottom: 15px; |
|
||||
padding-left: 13px; |
|
||||
span { |
|
||||
margin-left: 19px; |
|
||||
} |
|
||||
} |
|
||||
.local-none { |
|
||||
width: 100%; |
|
||||
text-align: center; |
|
||||
position: absolute; |
|
||||
// left: 50%; |
|
||||
top: 50%; |
|
||||
transform: translateY(-50%); |
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
/**滚动条的宽度*/ |
|
||||
::-webkit-scrollbar { |
|
||||
width: 8px; |
|
||||
height: 4px; |
|
||||
} |
|
||||
|
|
||||
//滚动条的滑块 |
|
||||
::-webkit-scrollbar-thumb { |
|
||||
background-color: #3f92f6; |
|
||||
border-radius: 4px; |
|
||||
} |
|
||||
</style> |
|
@ -1,134 +0,0 @@ |
|||||
<template> |
|
||||
<div v-loading.fullscreen.lock="bookLoading" class="hotbook-box" @scroll="lazyLoading"> |
|
||||
<div v-if="bookList.length > 0" class="most-book" @click="handleDetails(0)"> |
|
||||
<div class="most-book-img"> |
|
||||
<img :src="bookData[0].cover ? bookData[0].cover : ''" :onerror="defaultImg" /> |
|
||||
</div> |
|
||||
<div class="most-book-txt book-rack"> |
|
||||
<div class="txt"> |
|
||||
<h3>书名:{{ bookData[0].nbName || bookData[0].hbName }}</h3> |
|
||||
<p>作者:{{ bookData[0].nbAuthor || bookData[0].hbAuthor }}</p> |
|
||||
<p>出版社:{{ bookData[0].nbAuthor || bookData[0].hbAuthor }}</p> |
|
||||
<p>出版时间:{{ bookData[0].nbPublisherdate || bookData[0].hbPublisherdate }}</p> |
|
||||
</div> |
|
||||
</div> |
|
||||
</div> |
|
||||
<ul class="hotbook-list"> |
|
||||
<li v-for="(item,index) in bookList" :key="index" @click="handleDetails(index+1)"> |
|
||||
<div class="other-list-img"> |
|
||||
<img :src="item.cover ? item.cover : ''" :onerror="defaultImg" /> |
|
||||
</div> |
|
||||
<p class="book-name">{{ item.nbName || item.hbName }}</p> |
|
||||
</li> |
|
||||
</ul> |
|
||||
<BookDetails ref="detailDom" /> |
|
||||
</div> |
|
||||
</template> |
|
||||
|
|
||||
<script> |
|
||||
import BookDetails from './bookDetails.vue' |
|
||||
import { bookListCrud } from '../mixins/booklist.js' |
|
||||
export default { |
|
||||
name: 'BookList', |
|
||||
components: { BookDetails }, |
|
||||
mixins: [bookListCrud], |
|
||||
data() { |
|
||||
return { |
|
||||
} |
|
||||
}, |
|
||||
created() { |
|
||||
this.getBookData() |
|
||||
}, |
|
||||
mounted() { |
|
||||
}, |
|
||||
methods: { |
|
||||
} |
|
||||
} |
|
||||
</script> |
|
||||
|
|
||||
<style lang="scss" scoped> |
|
||||
@import "~@/assets/styles/index.scss"; |
|
||||
.hotbook-box{ |
|
||||
overflow: hidden; |
|
||||
overflow-y: auto; |
|
||||
height: calc(100vh - 210px); |
|
||||
} |
|
||||
.book-rack{ |
|
||||
margin: 160px 40px 28px 40px; |
|
||||
padding: 38px 40px 40px 400px; |
|
||||
height: 272px; |
|
||||
} |
|
||||
.most-book{ |
|
||||
position: relative; |
|
||||
.most-book-img{ |
|
||||
position: absolute; |
|
||||
left: 90px; |
|
||||
bottom: 20px; |
|
||||
width: 318px; |
|
||||
height: 382px; |
|
||||
display: flex; |
|
||||
align-items: center; |
|
||||
overflow: hidden; |
|
||||
img{ |
|
||||
display: block; |
|
||||
width: 100%; |
|
||||
vertical-align: middle; |
|
||||
object-fit: contain; |
|
||||
} |
|
||||
} |
|
||||
.txt{ |
|
||||
// margin-left: 452px; |
|
||||
color: #333; |
|
||||
h3{ |
|
||||
font-size: 40px; |
|
||||
font-weight: normal; |
|
||||
overflow: hidden; |
|
||||
white-space: nowrap; |
|
||||
text-overflow: ellipsis; |
|
||||
} |
|
||||
p{ |
|
||||
font-size: 30px; |
|
||||
margin-top: 8px; |
|
||||
overflow: hidden; |
|
||||
white-space: nowrap; |
|
||||
text-overflow: ellipsis; |
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
.hotbook-list{ |
|
||||
margin: 0 40px; |
|
||||
display: flex; |
|
||||
flex-wrap: wrap; |
|
||||
// justify-content: space-between; |
|
||||
li{ |
|
||||
margin-bottom: 20px; |
|
||||
margin-left: 20px; |
|
||||
width: 300px; |
|
||||
overflow: hidden; |
|
||||
.other-list-img{ |
|
||||
display: flex; |
|
||||
align-items: center; |
|
||||
width: 100%; |
|
||||
height: 360px; |
|
||||
overflow: hidden; |
|
||||
} |
|
||||
img{ |
|
||||
display: block; |
|
||||
width: 100%; |
|
||||
max-height: calc(100%); |
|
||||
vertical-align: middle; |
|
||||
object-fit: contain; |
|
||||
} |
|
||||
.book-name{ |
|
||||
width: 100%; |
|
||||
text-align: center; |
|
||||
overflow: hidden; |
|
||||
text-overflow:ellipsis; |
|
||||
white-space: nowrap; |
|
||||
} |
|
||||
} |
|
||||
& li:nth-child(3n+1){ |
|
||||
margin-left: 0; |
|
||||
} |
|
||||
} |
|
||||
</style> |
|
@ -1,51 +0,0 @@ |
|||||
<template> |
|
||||
<div class="header-time"> |
|
||||
<div class="header-text header-date">{{ nowDate }}</div> |
|
||||
<span class="icon iconfont"></span> |
|
||||
</div> |
|
||||
</template> |
|
||||
|
|
||||
<script> |
|
||||
import { getCurrentTime } from '@/utils/index' |
|
||||
|
|
||||
export default { |
|
||||
name: 'HeaderTop', |
|
||||
data() { |
|
||||
return { |
|
||||
nowDate: '' |
|
||||
} |
|
||||
}, |
|
||||
created() { |
|
||||
this.timer = setInterval(() => { |
|
||||
this.nowDate = getCurrentTime() |
|
||||
}, 1000) |
|
||||
}, |
|
||||
mounted() { |
|
||||
}, |
|
||||
methods: { |
|
||||
} |
|
||||
} |
|
||||
</script> |
|
||||
|
|
||||
<style lang="scss" scoped> |
|
||||
.header-time{ |
|
||||
display: flex; |
|
||||
justify-content: space-between; |
|
||||
position: absolute; |
|
||||
top: 0; |
|
||||
left: 0; |
|
||||
background-color: #3F92F6; |
|
||||
width: 100%; |
|
||||
height: 60px; |
|
||||
line-height: 60px; |
|
||||
font-size: 30px; |
|
||||
color: #fff; |
|
||||
padding: 0 40px; |
|
||||
span{ |
|
||||
width: 35px; |
|
||||
height: 45px; |
|
||||
font-size: 30px; |
|
||||
z-index: 1; |
|
||||
} |
|
||||
} |
|
||||
</style> |
|
@ -1,97 +0,0 @@ |
|||||
<template> |
|
||||
<div> |
|
||||
<div :class="[isNewBook ? 'list-small' : (isOtherBook ? 'list-middle' : 'list-big') ]"> |
|
||||
<div v-for="(item,index) in listData" :key="item.ranking" class="list-item" @click="handleDetails(index)"> |
|
||||
<div class="book-img"> |
|
||||
<img :src="item.cover" :onerror="defaultImg" /> |
|
||||
</div> |
|
||||
<div class="book-info"> |
|
||||
<h4 :class="['book-title', {'title-item': !isOtherBook}]">{{ item.nbName }}</h4> |
|
||||
<p class="book-author">{{ item.nbAuthor }}</p> |
|
||||
<div v-if="!isNewBook" class="book-num"> |
|
||||
<svg class="icon" aria-hidden="true"> |
|
||||
<use xlink:href="#icon-remen" /> |
|
||||
</svg> |
|
||||
<p>{{ item.num }}</p> |
|
||||
</div> |
|
||||
</div> |
|
||||
</div> |
|
||||
</div> |
|
||||
<BookDetails ref="detailDom" /> |
|
||||
</div> |
|
||||
</template> |
|
||||
|
|
||||
<script> |
|
||||
import { getBookDetailsByISBN } from '@/api/bookshelf' |
|
||||
import BookDetails from './bookDetails.vue' |
|
||||
|
|
||||
export default { |
|
||||
name: 'BookListItem', |
|
||||
components: { BookDetails }, |
|
||||
props: { |
|
||||
listData: { |
|
||||
type: Array, |
|
||||
default: function() { |
|
||||
return [] |
|
||||
} |
|
||||
}, |
|
||||
isOtherBook: { |
|
||||
type: Boolean, |
|
||||
default: function() { |
|
||||
return false |
|
||||
} |
|
||||
}, |
|
||||
isNewBook: { |
|
||||
type: Boolean, |
|
||||
default: function() { |
|
||||
return false |
|
||||
} |
|
||||
} |
|
||||
}, |
|
||||
data() { |
|
||||
return { |
|
||||
defaultImg: 'this.src="' + require('@/assets/images/default-img.png') + '"' |
|
||||
} |
|
||||
}, |
|
||||
watch: { |
|
||||
listData: function(newValue, oldValue) { |
|
||||
}, |
|
||||
isOtherBook: function(newValue, oldValue) { |
|
||||
}, |
|
||||
isNewBook: function(newValue, oldValue) { |
|
||||
} |
|
||||
}, |
|
||||
created() { |
|
||||
}, |
|
||||
mounted() { |
|
||||
}, |
|
||||
methods: { |
|
||||
handleDetails(index) { |
|
||||
const params = { |
|
||||
isbn: this.listData[index].isbn.replace(/\-/g, '') |
|
||||
} |
|
||||
getBookDetailsByISBN(params).then(res => { |
|
||||
this.$refs.detailDom.dialogVisible = true |
|
||||
if (res) { |
|
||||
this.$refs.detailDom.bookData = res |
|
||||
} else { |
|
||||
this.$refs.detailDom.bookData = { |
|
||||
srcUrl: this.listData[index].cover, |
|
||||
bookName: this.listData[index].nbName, |
|
||||
bookAuthor: this.listData[index].nbAuthor ? this.listData[index].nbAuthor : '暂无信息', |
|
||||
gist: '暂无简介', |
|
||||
Publish: '暂无信息', |
|
||||
places: [ |
|
||||
{ shelfName: '' } |
|
||||
] |
|
||||
} |
|
||||
} |
|
||||
}) |
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
</script> |
|
||||
|
|
||||
<style lang="scss"> |
|
||||
@import "~@/assets/styles/index.scss"; |
|
||||
</style> |
|