Browse Source

需求优化更新

master
xuhuajiao 1 month ago
parent
commit
836deefab1
  1. 123
      src/views/accessToLibrary/index.vue
  2. 32
      src/views/newBookRecommend/index.vue
  3. 89
      src/views/notice/index.vue
  4. 2
      src/views/readStar/index-height.vue
  5. 2
      src/views/readStar/index.vue

123
src/views/accessToLibrary/index.vue

@ -31,9 +31,7 @@ export default {
props: { props: {
isSelfService: { isSelfService: {
type: Boolean, type: Boolean,
default: function() {
return false
}
default: false
} }
}, },
data() { data() {
@ -43,70 +41,87 @@ export default {
dayOutNum: 0, dayOutNum: 0,
monthNum: 0, monthNum: 0,
totalNum: 0, totalNum: 0,
otherDoorOther: null
otherDoorOther: null,
abortController: null,
isPageHide: false
} }
}, },
created() { created() {
// 获取数据
this.getInitIntoNum() this.getInitIntoNum()
}, },
mounted() { mounted() {
// 每15秒获取一次
document.addEventListener('visibilitychange', this.handleVisibility)
this.startPoll()
},
beforeDestroy() {
this.stopPoll()
if (this.abortController) {
this.abortController.abort()
}
document.removeEventListener('visibilitychange', this.handleVisibility)
},
methods: {
handleVisibility() {
this.isPageHide = document.hidden
if (this.isPageHide) {
this.stopPoll()
} else {
this.startPoll()
}
},
startPoll() {
this.stopPoll()
this.timer = setInterval(() => { this.timer = setInterval(() => {
this.getInitIntoNum() this.getInitIntoNum()
}, 15000) }, 15000)
}, },
beforeDestroy() {
// 销毁定时器
this.$once('hook:beforeDestroy', () => {
stopPoll() {
if (this.timer) {
clearInterval(this.timer) clearInterval(this.timer)
})
this.timer = null
}
}, },
methods: {
getInitIntoNum() { getInitIntoNum() {
// http://192.168.99.118:8080/#/?doorCodes=D001&D002&D007&startTime=2023-01-01&endTime=2023-08-31
// this.otherDoorOther = window.location.href.split('?')[1]?.split('=')[1]
const currentURL = window.location.href
console.log(currentURL)
if (currentURL.indexOf('?') !== -1) {
const query = currentURL.split('?')[1]
console.log(query)
console.log(query.indexOf('startTime'))
if (query.indexOf('startTime') !== -1 || query.indexOf('endTime') !== -1) {
const paramsUrl = query.split('&')
console.log(paramsUrl)
let startTimeIndex = -1
for (let i = 0; i < paramsUrl.length; i++) {
const [key] = paramsUrl[i].split('=')
if (key === 'startTime' || key === 'endTime') {
startTimeIndex = i
break
}
}
// 去除 startTime 参数及其后面的参数
const filteredParams = startTimeIndex >= 0 ? paramsUrl.slice(0, startTimeIndex) : params
const newQueryString = filteredParams.join('&')
this.otherDoorOther = newQueryString.split('=')[1]
} else {
this.otherDoorOther = query.split('=')[1]
// 【修复】hash模式,#?后面的参数串
const fullUrl = window.location.href
const hashContent = fullUrl.split('#')[1] || ''
let queryStr = ''
if (hashContent.includes('?')) {
queryStr = hashContent.split('?')[1]
} }
console.log('queryStr', queryStr)
let otherDoorOther = null
if (queryStr) {
// 找到 &startTime= / &endTime= 的位置,在此截断,前面全部属于doorCodes值
let cutIndex = Infinity
const markers = ['&startTime=', '&endTime=']
for (const m of markers) {
const idx = queryStr.indexOf(m)
if (idx !== -1 && idx < cutIndex) {
cutIndex = idx
}
}
let doorCodesRaw
if (cutIndex !== Infinity) {
doorCodesRaw = queryStr.substring(0, cutIndex)
} else { } else {
this.otherDoorOther = null
doorCodesRaw = queryStr
}
// 去掉 doorCodes= 前缀
if (doorCodesRaw.startsWith('doorCodes=')) {
doorCodesRaw = doorCodesRaw.replace('doorCodes=', '')
} }
if (doorCodesRaw) {
otherDoorOther = doorCodesRaw.replace(/&/g, '、')
}
}
this.otherDoorOther = otherDoorOther
console.log('otherDoorOther', otherDoorOther)
const startTime = this.$route.query.startTime const startTime = this.$route.query.startTime
const endTime = this.$route.query.endTime const endTime = this.$route.query.endTime
console.log('otherDoorOther', this.otherDoorOther)
if (this.otherDoorOther && this.otherDoorOther !== '' && this.otherDoorOther.indexOf('&')) {
this.otherDoorOther = this.otherDoorOther.replace(/\&/g, '、')
} else {
this.otherDoorOther = null
}
console.log('otherDoorOther2', this.otherDoorOther)
let params let params
if (!this.isSelfService) { if (!this.isSelfService) {
params = { params = {
@ -121,7 +136,14 @@ export default {
endTime: endTime endTime: endTime
} }
} }
FetchInitIntoNum(params).then((res) => {
// 增加请求取消(如果你的axios封装支持signal就打开,不支持注释掉abort相关)
if (this.abortController) this.abortController.abort()
this.abortController = new AbortController()
FetchInitIntoNum(params, {
signal: this.abortController?.signal
}).then((res) => {
if (res.errCode === 0) { if (res.errCode === 0) {
this.dayNum = res.data.dayPeopleNum this.dayNum = res.data.dayPeopleNum
this.monthNum = res.data.monthPeopleNum this.monthNum = res.data.monthPeopleNum
@ -130,6 +152,11 @@ export default {
} else { } else {
this.$message.error('接口错误') this.$message.error('接口错误')
} }
}).catch(err => {
// abort取消的请求不弹报错
if (err.name !== 'AbortError') {
console.error('进馆人数接口异常', err)
}
}) })
} }
} }

32
src/views/newBookRecommend/index.vue

@ -42,7 +42,8 @@
</template> </template>
<script> <script>
import { FetchNewBookRecommend, FetchCoverByISBN } from '@/api/library'
// FetchCoverByISBN
import { FetchNewBookRecommend } from '@/api/library'
import { swiper, swiperSlide } from 'vue-awesome-swiper' import { swiper, swiperSlide } from 'vue-awesome-swiper'
import 'swiper/dist/css/swiper.css' import 'swiper/dist/css/swiper.css'
// import result from './data.json' // import result from './data.json'
@ -181,18 +182,25 @@ export default {
if (res.errCode === 0) { if (res.errCode === 0) {
const bookList = res.data.newbookList const bookList = res.data.newbookList
const bookWithCovers = await Promise.all(
bookList.map(async(item) => {
const isbn = item.isbn.replace(/\-/g, '').trim()
try {
const coverRes = await FetchCoverByISBN({ isbn })
return { ...item, cover: coverRes || '' }
} catch (e) {
console.error(`获取ISBN:${isbn}封面失败`, e)
return { ...item, cover: '' }
}
// const bookWithCovers = await Promise.all(
// bookList.map(async(item) => {
// const isbn = item.isbn.replace(/\-/g, '').trim()
// try {
// const coverRes = await FetchCoverByISBN({ isbn })
// return { ...item, cover: coverRes || '' }
// } catch (e) {
// console.error(`获取ISBN:${isbn}封面失败`, e)
// return { ...item, cover: '' }
// }
// })
// )
const bookWithCovers = bookList.map(item => {
// 封面地址 = 基础API + /downloadFile/ + 图片路径
const cover = item.nbImgPath
? `${process.env.VUE_APP_BASE_API}/downloadFile/${item.nbImgPath}`
: ''
return { ...item, cover }
}) })
)
// 赋值原始数据(20条) // 赋值原始数据(20条)
this.rankingList = bookWithCovers this.rankingList = bookWithCovers

89
src/views/notice/index.vue

@ -4,8 +4,6 @@
<div class="common-title">通知公告</div> <div class="common-title">通知公告</div>
<div class="small-module module-content"> <div class="small-module module-content">
<span class="notice-icon-gif" /> <span class="notice-icon-gif" />
<!-- 核心:给容器加固定宽度,避免宽度溢出导致滚动失效 -->
<div ref="box" class="seamless-warp"> <div ref="box" class="seamless-warp">
<div ref="text" class="notice-txt" v-html="content" /> <div ref="text" class="notice-txt" v-html="content" />
</div> </div>
@ -21,22 +19,51 @@ export default {
data() { data() {
return { return {
content: '', content: '',
scrollTimer: null, // 滚动定时器
transitionTimer: null, // 过渡结束定时器
boxH: 0, // 容器高度
textH: 0, // 内容高度
duration: 40000 // 单次滚动时长
scrollTimer: null,
transitionTimer: null,
boxH: 0,
textH: 0,
duration: 40000,
isDestroyed: false, // 标记组件是否销毁
isScrollRunning: false // 防止重复启动滚动
} }
}, },
mounted() { mounted() {
this.isDestroyed = false
document.addEventListener('visibilitychange', this.handleVisibility)
this.getInitNotice() this.getInitNotice()
}, },
beforeDestroy() { beforeDestroy() {
// 销毁时清除所有定时器
this.isDestroyed = true
this.isScrollRunning = false
if (this.scrollTimer) clearInterval(this.scrollTimer) if (this.scrollTimer) clearInterval(this.scrollTimer)
if (this.transitionTimer) clearTimeout(this.transitionTimer) if (this.transitionTimer) clearTimeout(this.transitionTimer)
// ✅ 移除dom事件,防止内存泄漏
const text = this.$refs.text
if (text) {
text.removeEventListener('transitionend', this.handleTransitionEnd)
}
document.removeEventListener('visibilitychange', this.handleVisibility)
}, },
methods: { methods: {
// 页面切后台/切前台
handleVisibility() {
if (this.isDestroyed) return
if (document.hidden) {
// 页面隐藏,清除延时,暂停滚动循环
if (this.transitionTimer) {
clearTimeout(this.transitionTimer)
this.transitionTimer = null
}
} else {
// 切回来,继续滚动
if (this.isScrollRunning) {
this.rollToBottom()
}
}
},
escapeHtml(str) { escapeHtml(str) {
if (!str) return '' if (!str) return ''
var arrEntities = { var arrEntities = {
@ -48,14 +75,16 @@ export default {
} }
return str.replace(/&(lt|gt|nbsp|amp|quot);/ig, (all, t) => arrEntities[t]) return str.replace(/&(lt|gt|nbsp|amp|quot);/ig, (all, t) => arrEntities[t])
.replace(/<pre>|<\/pre>/gi, '') .replace(/<pre>|<\/pre>/gi, '')
.replace(/\\r\\n/g, '') // 移除多余换行符
.replace(/\\r\\n/g, '')
}, },
getInitNotice() { getInitNotice() {
if (this.isDestroyed) return
FetchInitNotice().then(res => { FetchInitNotice().then(res => {
if (this.isDestroyed) return
if (res.errCode === 0) { if (res.errCode === 0) {
this.content = this.escapeHtml(res.data) this.content = this.escapeHtml(res.data)
// 等DOM完全渲染后再启动滚动
this.$nextTick(() => { this.$nextTick(() => {
if (this.isDestroyed) return
this.startScroll() this.startScroll()
}) })
} }
@ -64,65 +93,61 @@ export default {
}) })
}, },
startScroll() { startScroll() {
if (this.isDestroyed || this.isScrollRunning) return
const box = this.$refs.box const box = this.$refs.box
const text = this.$refs.text const text = this.$refs.text
// 先打印调试,看是否获取到DOM和高度
console.log('容器DOM:', box)
console.log('内容DOM:', text)
if (!box || !text) { if (!box || !text) {
console.log('DOM未获取到,滚动启动失败') console.log('DOM未获取到,滚动启动失败')
return return
} }
// 强制计算高度(解决rem布局高度计算延迟)
this.boxH = box.clientHeight || parseInt(getComputedStyle(box).height) this.boxH = box.clientHeight || parseInt(getComputedStyle(box).height)
this.textH = text.offsetHeight || parseInt(getComputedStyle(text).height) this.textH = text.offsetHeight || parseInt(getComputedStyle(text).height)
console.log('容器高度:', this.boxH, '内容高度:', this.textH) console.log('容器高度:', this.boxH, '内容高度:', this.textH)
// 内容不够高,不滚动
if (this.textH <= this.boxH) { if (this.textH <= this.boxH) {
console.log('内容高度小于容器,无需滚动') console.log('内容高度小于容器,无需滚动')
this.isScrollRunning = false
return return
} }
// 初始化样式
// 重置样式
text.style.position = 'absolute' text.style.position = 'absolute'
text.style.top = '0px' text.style.top = '0px'
text.style.left = '0px' text.style.left = '0px'
text.style.width = '100%' text.style.width = '100%'
text.style.transition = 'none' text.style.transition = 'none'
// 监听过渡结束事件,实现循环
// 先解绑旧事件,避免重复绑定
text.removeEventListener('transitionend', this.handleTransitionEnd)
text.addEventListener('transitionend', this.handleTransitionEnd) text.addEventListener('transitionend', this.handleTransitionEnd)
// 启动第一次滚动
this.isScrollRunning = true
this.rollToBottom() this.rollToBottom()
}, },
// 滚动到底部
rollToBottom() { rollToBottom() {
if (this.isDestroyed || !this.isScrollRunning) return
const text = this.$refs.text const text = this.$refs.text
// 重置过渡,立即回到顶部
if (!text) return
text.style.transition = 'none' text.style.transition = 'none'
text.style.top = '0px' text.style.top = '0px'
// 重新设置过渡,滚动到底部
setTimeout(() => {
// 使用requestAnimationFrame替代固定100ms延时,等待浏览器重绘完成
requestAnimationFrame(() => {
if (this.isDestroyed || !this.$refs.text) return
text.style.transition = `top ${this.duration}ms linear` text.style.transition = `top ${this.duration}ms linear`
text.style.top = `-${this.textH - this.boxH}px` text.style.top = `-${this.textH - this.boxH}px`
}, 100)
})
}, },
// 过渡结束处理函数
handleTransitionEnd() {
// const text = this.$refs.text
// 清除之前的定时器,避免重复触发
if (this.transitionTimer) clearTimeout(this.transitionTimer)
handleTransitionEnd(e) {
// 只处理text本身的transition事件,避免子元素触发
if (this.isDestroyed || e.target !== this.$refs.text) return
// 停留2秒后重新滚动
if (this.transitionTimer) clearTimeout(this.transitionTimer)
this.transitionTimer = setTimeout(() => { this.transitionTimer = setTimeout(() => {
this.rollToBottom() this.rollToBottom()
}, 2000) // 2000毫秒 = 2秒
}, 2000)
} }
} }
} }

2
src/views/readStar/index-height.vue

@ -124,7 +124,7 @@ export default {
'starttime': startDate, 'starttime': startDate,
'endtime': endDate, 'endtime': endDate,
'rownum': 6, 'rownum': 6,
'nordtype': 'JXTSG_E'
'nordtype': 'JXTSG_E,1201006,1201007,1201008,1201023,1201030,1201032'
} }
FetchReadRanking(params).then(res => { FetchReadRanking(params).then(res => {

2
src/views/readStar/index.vue

@ -81,7 +81,7 @@ export default {
'starttime': startDate, 'starttime': startDate,
'endtime': endDate, 'endtime': endDate,
'rownum': 6, 'rownum': 6,
'nordtype': 'JXTSG_E'
'nordtype': 'JXTSG_E,1201006,1201007,1201008,1201023,1201030,1201032'
} }
FetchReadRanking(params).then(res => { FetchReadRanking(params).then(res => {

Loading…
Cancel
Save