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.
919 lines
32 KiB
919 lines
32 KiB
<template>
|
|
<div style="padding: 0 .4rem;">
|
|
<div class="pageOne-database">
|
|
<!-- 到馆统计 -->
|
|
<div class="database-left">
|
|
<h3 class="database-title">到馆统计</h3>
|
|
<ul class="inLib-num">
|
|
<li
|
|
v-for="(item, index) in leftData"
|
|
:key="index"
|
|
:class="[{'allTotal': item.id === 'allTotal'}, {'lastYearTotal': item.id === 'lastYearTotal'}]"
|
|
>
|
|
<div class="pageLeft-flop-box">
|
|
<div>
|
|
<span v-for="(ls, i) in item.valueArr" :key="item.id + i" :class="[{'flop-figure': !isNaN(ls)}, {'flop-comma': isNaN(ls)}]">
|
|
<i v-if="!isNaN(ls)">0123456789</i>
|
|
<span v-else>{{ ls }}</span>
|
|
</span>
|
|
<em>人</em>
|
|
</div>
|
|
</div>
|
|
<div class="flop-item-name">{{ item.name }}</div>
|
|
</li>
|
|
</ul>
|
|
<ul class="pageOne-left-progress">
|
|
<li v-for="(item,index) in progressData" :key="index" :class="[{'blue-progress':item.type===1 || item.type === 2},{'orange-progress':item.type===3 || item.type === 4}]">
|
|
<p>{{ item.name }}</p>
|
|
<span class="progress-num">{{ item.value }}<i>人</i></span>
|
|
<el-progress :percentage="computedPercentage(item)" :stroke-width="8" :show-text="false" />
|
|
</li>
|
|
</ul>
|
|
</div>
|
|
<!-- 中间大数据 -->
|
|
<!-- <div class="database-middle">
|
|
<div class="database-box">
|
|
<a class="logo" href="#" />
|
|
<div class="ring ring1">
|
|
<div class="particle" />
|
|
</div>
|
|
<div class="ring ring2">
|
|
<div class="particle" />
|
|
</div>
|
|
<div class="ring ring3">
|
|
<div class="particle" />
|
|
</div>
|
|
</div>
|
|
<div v-for="(item,index) in middleData" :key="index" :class="['middle-item', {'totalBook': item.id === 'totalBook'}, {'fansNum': item.id === 'fansNum'}, {'lendingNum': item.id === 'lendingNum'}, {'cardNum': item.id === 'cardNum'}]">
|
|
<p>{{ item.name }}</p>
|
|
<div class="small-module">
|
|
<div class="chartNum">
|
|
<div class="box-items">
|
|
<li v-for="(e,i) in item.valueArr" :key="i" class="number-item">
|
|
<span><i ref="numberItem" class="item">0123456789</i></span>
|
|
</li>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div> -->
|
|
<div class="database-middle">
|
|
<div class="middle-img">
|
|
<div class="middle-img-book" />
|
|
<div class="wq" />
|
|
<!-- <div class="line-box">
|
|
<div class="box">
|
|
<div class="ball" />
|
|
</div>
|
|
</div> -->
|
|
<div class="middle-img-bottom">
|
|
<div style="width: 360; height: 200px; position: relative; margin: 50px 0 0 30px;">
|
|
<svg width="360" height="200">
|
|
<path d="M0 80 S 170 160, 400 70" />
|
|
</svg>
|
|
<div class="rect qxRect" />
|
|
</div>
|
|
</div>
|
|
<div class="middle-img-dot" />
|
|
</div>
|
|
<div v-for="(item,index) in middleData" :key="index" :class="['middle2-item', {'totalBook': item.id === 'totalBook'}, {'fansNum': item.id === 'fansNum'}, {'lendingNum': item.id === 'lendingNum'}, {'cardNum': item.id === 'cardNum'}]">
|
|
<p>{{ item.name }}</p>
|
|
<div class="middle-num">
|
|
<div class="small-module">
|
|
<div class="chartNum">
|
|
<div class="box-items">
|
|
<li v-for="(e,i) in item.valueArr" :key="i" :class="!isNaN(e) ? 'number-item':'number-item num-dot'">
|
|
<span v-if="!isNaN(e)" class="items-int"><i ref="numberItem" class="item">0123456789</i></span>
|
|
<span v-else>{{ e }}</span>
|
|
<!-- <span><i ref="numberItem" class="item">0123456789</i></span> -->
|
|
</li>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<span v-if="item.id === 'totalBook'" class="middle-unit">册</span>
|
|
<span v-if="item.id === 'fansNum'" class="middle-unit">人</span>
|
|
<span v-if="item.id === 'cardNum'" class="middle-unit">个</span>
|
|
<span v-if="item.id === 'lendingNum'" class="middle-unit">册</span>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<!-- 热门搜索 -->
|
|
<div class="database-right">
|
|
<h3 class="database-title">热门搜索</h3>
|
|
<div class="tagcloud-main">
|
|
<div v-if="tagList.length !== 0" id="tagscloud" ref="tagcloudall" class="tagscloud">
|
|
<!-- <a v-for="(item,index) in hotTagData" :key="index" :class="'tagc' + ((index % 4) + 1)">
|
|
{{ item }}
|
|
</a> -->
|
|
<a v-for="(item,index) in tagList" :key="index" :class="'tagc' + ((index % 4) + 1)">{{ item }}</a>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<!-- 底部 图书推荐 -->
|
|
<div class="pageOne-book">
|
|
<h3 class="database-title">图书推荐</h3>
|
|
<div class="pageOne-book-content">
|
|
<div class="scrollBox">
|
|
<vue-seamless-scroll
|
|
ref="listData"
|
|
:data="listData1"
|
|
:class-option="defaultOption"
|
|
class="seamless01"
|
|
>
|
|
<ul>
|
|
<li v-for="(item, index) in listData1" :key="index">
|
|
<div class="bord">
|
|
<div class="book-img">
|
|
<img :src="item.nbImgPath" :onerror="defaultImg">
|
|
</div>
|
|
</div>
|
|
</li>
|
|
</ul>
|
|
</vue-seamless-scroll>
|
|
<vue-seamless-scroll
|
|
ref="listData2"
|
|
:data="listData2"
|
|
:class-option="default2Option"
|
|
class="seamless02"
|
|
>
|
|
<ul>
|
|
<li v-for="(item, index) in listData2" :key="index">
|
|
<div class="bord">
|
|
<div class="book-img">
|
|
<img :src="item.nbImgPath" :onerror="defaultImg">
|
|
</div>
|
|
</div>
|
|
</li>
|
|
</ul>
|
|
</vue-seamless-scroll>
|
|
</div>
|
|
<div class="wechat-code">
|
|
<div class="wechat-img">
|
|
<img :src="wecharQrCodeSrc">
|
|
</div>
|
|
<span>微信扫一扫关注</span>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</template>
|
|
|
|
<script>
|
|
import { FetchInitSetting, FetchUsertotal, FetchLibBookTotal, FetchHotSearch, FetchFansCount, FetchLendingTotal, FetchNewBook, FetchMarcByISBN } from '@/api/library'
|
|
export default {
|
|
name: 'PageOne',
|
|
data() {
|
|
return {
|
|
intervalLeft: null,
|
|
isDataLoaded: false,
|
|
pageOneVisitBase: '0', // 本年到馆基础数
|
|
wecharQrCodeSrc: null,
|
|
newList: [],
|
|
listData1: [],
|
|
listData2: [],
|
|
defaultImg: 'this.src="' + require('@/assets/images/book_03.png') + '"',
|
|
leftData: [],
|
|
progressData: [],
|
|
hotTagData: [],
|
|
middleData: [],
|
|
tagList: [],
|
|
// 热门搜索的
|
|
radius: 160,
|
|
dtr: Math.PI / 180,
|
|
d: 200,
|
|
mcList: [],
|
|
active: false,
|
|
lasta: 1,
|
|
lastb: 1,
|
|
distr: true,
|
|
tspeed: 4,
|
|
size: 200,
|
|
mouseX: 0,
|
|
mouseY: 20,
|
|
howElliptical: 1,
|
|
oList: null,
|
|
oA: null,
|
|
sa: 0,
|
|
ca: 0,
|
|
sb: 0,
|
|
cb: 0,
|
|
sc: 0,
|
|
cc: 0
|
|
}
|
|
},
|
|
computed: {
|
|
defaultOption() {
|
|
return {
|
|
step: 0.5, // 数值越大速度滚动越快
|
|
limitMoveNum: 4, // 开始无缝滚动的数据量 this.dataList.length
|
|
hoverStop: true, // 是否开启鼠标悬停stop
|
|
direction: 2, // 0向下 1向上 2向左 3向右
|
|
openWatch: true, // 开启数据实时监控刷新dom
|
|
singleHeight: 0, // 单步运动停止的高度(默认值0是无缝不停止的滚动) direction => 0/1
|
|
singleWidth: 0, // 单步运动停止的宽度(默认值0是无缝不停止的滚动) direction => 2/3
|
|
waitTime: 1000 // 单步运动停止的时间(默认值1000ms)
|
|
}
|
|
},
|
|
default2Option() {
|
|
return {
|
|
step: 0.5, // 数值越大速度滚动越快
|
|
limitMoveNum: 4, // 开始无缝滚动的数据量 this.dataList.length
|
|
hoverStop: true, // 是否开启鼠标悬停stop
|
|
direction: 3, // 0向下 1向上 2向左 3向右
|
|
openWatch: true, // 开启数据实时监控刷新dom
|
|
singleHeight: 0, // 单步运动停止的高度(默认值0是无缝不停止的滚动) direction => 0/1
|
|
singleWidth: 0, // 单步运动停止的宽度(默认值0是无缝不停止的滚动) direction => 2/3
|
|
waitTime: 1000 // 单步运动停止的时间(默认值1000ms)
|
|
}
|
|
},
|
|
computedPercentage() {
|
|
return (item) => {
|
|
if (item.type === 1) {
|
|
return item.value > this.getType3Value() ? 100 : 70
|
|
} else if (item.type === 2) {
|
|
return item.value > this.getType4Value() ? 100 : 70
|
|
} else if (item.type === 3) {
|
|
return item.value > this.getType1Value() ? 100 : 70
|
|
} else if (item.type === 4) {
|
|
return item.value > this.getType2Value() ? 100 : 70
|
|
}
|
|
}
|
|
}
|
|
},
|
|
async created() {
|
|
this.getInitData()
|
|
this.getMiddleAllData()
|
|
this.getHotSearch()
|
|
this.getNewBook()
|
|
},
|
|
beforeDestroy() {
|
|
clearInterval(this.intervalLeft)
|
|
this.intervalLeft = null
|
|
},
|
|
activated() {
|
|
this.pageOneVisitBase = 0
|
|
this.getInitData()
|
|
},
|
|
deactivated() {
|
|
|
|
},
|
|
mounted() {
|
|
if (localStorage.getItem('wecharQrCodeSrc')) {
|
|
this.wecharQrCodeSrc = localStorage.getItem('wecharQrCodeSrc')
|
|
}
|
|
},
|
|
methods: {
|
|
getInitData() {
|
|
// visitBase 本年到馆基础数
|
|
// wecharQrCode 二维码 用/downloadFile/+wecharQrCode
|
|
// iNotice 公告
|
|
const linkSrc = process.env.VUE_APP_BASE_API
|
|
FetchInitSetting().then(res => {
|
|
const result = JSON.parse(res.data)
|
|
this.pageOneVisitBase = result.visitBase
|
|
this.wecharQrCodeSrc = linkSrc + '/downloadFile' + result.wecharQrCode
|
|
this.initLeftPreview(result)
|
|
// this.intervalLeft = setInterval(() => {
|
|
// this.getInitData()
|
|
// }, 10000)
|
|
})
|
|
},
|
|
initLeftPreview(result) {
|
|
this.progressData = []
|
|
this.leftData = []
|
|
|
|
// visitBase 本年累计人次
|
|
// visitBaseCheck 是否直接显示 0false 1true
|
|
|
|
// lastYearVisitBase 去年累计人次
|
|
|
|
// todayVisitBase 今日人次
|
|
// todayVisitBaseCheck 是否显示
|
|
|
|
// yesterdayVisitBase 昨天人次
|
|
// yesterdayVisitBaseCheck 是否显示
|
|
|
|
// thisMonthVisitBase 本月人次
|
|
// thisMonthVisitBaseCheck 是否显示
|
|
|
|
// lastMonthVisitBase 上个月人次
|
|
// lastMonthVisitBaseCheck 是否显示
|
|
|
|
const baseTotal = this.pageOneVisitBase // 本年到馆人数
|
|
console.log('假设本年到馆人数', baseTotal)
|
|
// 本年到馆/12个月 = 月基数
|
|
const monthBase = Math.floor(baseTotal / 12) // 月基数
|
|
console.log('月基数', monthBase)
|
|
// 月随机数(-100到200之间)
|
|
const randomMonth = Math.floor(Math.random() * (200 - (-100) + 1)) + (-100)
|
|
|
|
const now = new Date()
|
|
const year = now.getFullYear() // 当前年份
|
|
const month = now.getMonth() + 1 // 当前月份
|
|
const daysInMonth = new Date(year, month, 0).getDate() // 当月天数
|
|
console.log('当月天数', daysInMonth)
|
|
// 月基数/当月天数(28、29、30、31)= 日基数
|
|
const dayBase = Math.floor(monthBase / daysInMonth) // 日基数
|
|
console.log('日基数', dayBase)
|
|
// 本年累计=月基数*月份+月随机数(-100到200之间)
|
|
let nowYearCount
|
|
if (result.visitBaseCheck === '1') {
|
|
nowYearCount = result.visitBase
|
|
} else {
|
|
nowYearCount = Math.floor(monthBase * month + randomMonth) // 本年累计
|
|
}
|
|
console.log('本年累计', nowYearCount)
|
|
// 昨日到馆=日基数+日随机数(-20到50之间)
|
|
let yesterdayCount = 0
|
|
if (result.yesterdayVisitBaseCheck === '1') {
|
|
yesterdayCount = result.yesterdayVisitBase
|
|
} else {
|
|
const randomDay = Math.floor(Math.random() * (50 - (-20) + 1)) + (-20) // 日随机数(-20到50之间)
|
|
yesterdayCount = localStorage.getItem('yesterdayCountCache') ? localStorage.getItem('yesterdayCountCache') : dayBase + randomDay // 昨日到馆
|
|
}
|
|
console.log('昨日到馆', yesterdayCount)
|
|
// 上月到馆=月基数+月随机数(-100到200之间)
|
|
let lastMonthCount = 0
|
|
if (result.lastMonthVisitBaseCheck === '1') {
|
|
lastMonthCount = result.lastMonthVisitBase
|
|
} else {
|
|
lastMonthCount = localStorage.getItem('lastMonthCountCache') ? localStorage.getItem('lastMonthCountCache') : monthBase + randomMonth
|
|
}
|
|
console.log('上月到馆', lastMonthCount)
|
|
|
|
// 日基数/10小时=小时基数
|
|
const hourBase = Math.floor(dayBase / 10) // 小时基数
|
|
console.log('小时基数', hourBase)
|
|
// 图书馆营业时间(8:00-18:00共10小时)
|
|
// 8:00-9:00 算第1个小时、9:00-10:00算第2个小时、以此类推
|
|
const openTime = 8 // 开门时间
|
|
const closeTime = 18 // 结束时间
|
|
const currentHour = now.getHours() // 当前时间点
|
|
|
|
// 今日到馆=小时基数 * 第N小时+小时随机数(-5到10之间)
|
|
let todayCount = 0
|
|
if (result.todayVisitBaseCheck === '1') {
|
|
todayCount = result.todayVisitBase
|
|
} else {
|
|
if (currentHour < openTime || currentHour >= closeTime) {
|
|
console.log('当前时间不在图书馆营业时间内')
|
|
todayCount = 0
|
|
} else {
|
|
const N = currentHour - openTime
|
|
console.log('第N个小时', N)
|
|
const randomHour = Math.floor(Math.random() * (10 - (-5) + 1)) + (-5) // 小时随机数(-5到10之间)
|
|
todayCount = Math.floor(hourBase * N + randomHour) // 今日到馆
|
|
}
|
|
}
|
|
console.log('今日到馆', todayCount)
|
|
// 本月到馆=月基数 * (当前月的日期dd/当前月的天数)+ 月随机数(-100到200之间)
|
|
let nowMonthCount = 0
|
|
if (result.thisMonthVisitBaseCheck === '1') {
|
|
nowMonthCount = result.thisMonthVisitBase
|
|
} else {
|
|
nowMonthCount = Math.floor(monthBase * (now.getDate() / daysInMonth) + randomMonth) // 本月到馆
|
|
}
|
|
console.log('本月到馆', nowMonthCount)
|
|
|
|
this.progressData.push(
|
|
{
|
|
name: '今日到馆',
|
|
value: todayCount,
|
|
type: 1
|
|
},
|
|
{
|
|
name: '本月到馆',
|
|
value: nowMonthCount,
|
|
type: 2
|
|
},
|
|
{
|
|
name: '昨日到馆',
|
|
value: yesterdayCount,
|
|
type: 3
|
|
},
|
|
{
|
|
name: '上月到馆',
|
|
value: lastMonthCount,
|
|
type: 4
|
|
}
|
|
)
|
|
|
|
this.leftData.push({
|
|
id: 'allTotal',
|
|
name: '本年累计到馆',
|
|
value: this.$parent.formatter(nowYearCount),
|
|
valueArr: this.$parent.formatter(nowYearCount).split('')
|
|
},
|
|
{
|
|
id: 'lastYearTotal',
|
|
name: '去年累计到馆',
|
|
value: this.$parent.formatter(result.lastYearVisitBase),
|
|
valueArr: this.$parent.formatter(result.lastYearVisitBase).split('')
|
|
})
|
|
|
|
this.$parent.timedRefresh(this.leftData, 'left')
|
|
|
|
// 昨日到馆、上月到馆存一个缓存!当前第一次计算好之后就不变了!
|
|
localStorage.setItem('yesterdayCountCache', yesterdayCount)
|
|
localStorage.setItem('lastMonthCountCache', lastMonthCount)
|
|
},
|
|
|
|
// 热门搜索
|
|
getHotSearch() {
|
|
const params = {
|
|
'size': 40
|
|
}
|
|
FetchHotSearch(params).then(res => {
|
|
this.hotTagData = res.data.replace(/^\[|\]$/g, '').split(', ')
|
|
this.$nextTick(() => {
|
|
this.tagList = this.hotTagData
|
|
this.onReady()
|
|
})
|
|
})
|
|
},
|
|
getMiddleAllData() {
|
|
Promise.all([
|
|
this.getLibBookTotal(),
|
|
this.getUserTotal(),
|
|
this.getFansNum(),
|
|
this.getLendingTotal()
|
|
]).then(([libBookTotal, userCardNum, fansNum, lendingTotal]) => {
|
|
this.middleData.push(
|
|
{
|
|
id: 'totalBook',
|
|
name: '藏书总量',
|
|
value: libBookTotal,
|
|
valueArr: this.$parent.formatter(libBookTotal).toString().split('')
|
|
},
|
|
{
|
|
id: 'cardNum',
|
|
name: '累计办证',
|
|
value: userCardNum,
|
|
valueArr: this.$parent.formatter(userCardNum).toString().split('')
|
|
},
|
|
{
|
|
id: 'fansNum',
|
|
name: '粉丝数量',
|
|
value: fansNum,
|
|
valueArr: this.$parent.formatter(fansNum).toString().split('')
|
|
},
|
|
{
|
|
id: 'lendingNum',
|
|
name: '累计借出',
|
|
value: lendingTotal,
|
|
valueArr: this.$parent.formatter(lendingTotal).toString().split('')
|
|
}
|
|
)
|
|
this.$parent.timedRefresh(this.middleData, 'middle')
|
|
// setTimeout(() => {
|
|
// this.$parent.timedRefresh(this.middleData, 'middle')
|
|
// }, 8000)
|
|
}).catch(error => {
|
|
console.error('Error fetching data:', error)
|
|
})
|
|
},
|
|
// 馆藏量
|
|
getLibBookTotal() {
|
|
const params = {
|
|
'libcode': 'LSJDFG,LJPFG,DCDFG,QYTSG,SJLFG,XMDFG,FXLFG,QLQFG,SEDSG,MZZFG,GYTZFG,KJSKCFG,JBTZFG,SKTZFG,XJZFG,PSZFG,DZQZFG,WXJDFG,CHJDFG,BSZFG,BZHFG',
|
|
'starttime': '2000-01-01',
|
|
'endtime': '2034-01-01'
|
|
}
|
|
return FetchLibBookTotal(params).then(res => {
|
|
const result = JSON.parse(res.data)
|
|
if (result.success & result.resultlist.length !== 0) {
|
|
return result.resultlist.reduce((acc, obj) => acc + obj.GCL, 0)
|
|
} else {
|
|
return 0
|
|
}
|
|
}).catch(error => {
|
|
console.error('Error', error)
|
|
return 0
|
|
})
|
|
},
|
|
// 累计办证
|
|
getTotalForLibcode(libcode) {
|
|
const params = {
|
|
'libcode': libcode,
|
|
'startdate': this.getFormattedDate(new Date(), -1),
|
|
'enddate': this.getFormattedDate(new Date()),
|
|
'isrdtype': 0
|
|
}
|
|
return FetchUsertotal(params).then(res => {
|
|
const result = JSON.parse(res.data)
|
|
if (result.success && result.pagedata.length > 0) {
|
|
return result.pagedata[0].count
|
|
} else {
|
|
throw new Error('Failed' + libcode)
|
|
}
|
|
}).catch(error => {
|
|
console.error('Error' + libcode, error)
|
|
return 0
|
|
})
|
|
},
|
|
getUserTotal() {
|
|
const libraries = ['QYTSG', 'SJLFG', 'FXLFG', 'SEDSG', 'BZHFG']
|
|
const getTotalPromises = libraries.map(libcode => this.getTotalForLibcode(libcode))
|
|
return Promise.all(getTotalPromises)
|
|
.then(counts => counts.reduce((sum, count) => sum + parseInt(count, 10), 0))
|
|
.catch(error => {
|
|
console.error('Error', error)
|
|
return 0
|
|
})
|
|
},
|
|
// 粉丝数量
|
|
getFansNum() {
|
|
return FetchFansCount().then(res => {
|
|
return res.data ? parseInt(res.data) : 0
|
|
}).catch(error => {
|
|
console.error('Error', error)
|
|
return 0
|
|
})
|
|
},
|
|
// 累计借出
|
|
getLendingTotal() {
|
|
return FetchLendingTotal().then(res => {
|
|
const result = JSON.parse(res.data)
|
|
if (result.success & result.resultlist.length !== 0) {
|
|
return result.resultlist.filter(item => item.LIBCODE !== '999').reduce((acc, obj) => acc + obj.JCC, 0)
|
|
} else {
|
|
return 0
|
|
}
|
|
}).catch(error => {
|
|
console.error('Error', error)
|
|
return 0
|
|
})
|
|
},
|
|
// bottom - 图书推荐
|
|
getNewBook() {
|
|
const params = {
|
|
'size': 40
|
|
}
|
|
FetchNewBook(params).then(res => {
|
|
// 图片地址格式 http://192.168.99.67:8080/downloadFile/qytsg/ae281b90-b100-4541-9379-3e104854652c.png
|
|
const linkSrc = process.env.VUE_APP_BASE_API
|
|
this.newList = res.data.map(item => {
|
|
if (item.nbImgPath) {
|
|
item.nbImgPath = linkSrc + '/downloadFile' + item.nbImgPath
|
|
return Promise.resolve(item)
|
|
} else {
|
|
const params = {
|
|
'sIsbn': item.isbn
|
|
}
|
|
return FetchMarcByISBN(params).then(response => {
|
|
const result = JSON.parse(response.data)[0]
|
|
if (result.srcurl) {
|
|
item.nbImgPath = result.srcurl
|
|
return item
|
|
} else if (result.img) {
|
|
item.nbImgPath = 'data:image/png;base64,' + result.img
|
|
return item
|
|
} else {
|
|
return null // 或者根据需求返回其他值或处理
|
|
}
|
|
})
|
|
}
|
|
})
|
|
|
|
Promise.all(this.newList).then(results => {
|
|
// 过滤掉返回的空项(根据实际需求)
|
|
this.newList = results.filter(item => item !== null)
|
|
// 一分为二得两行
|
|
const halfLength = Math.ceil(this.newList.length / 2)
|
|
this.listData1 = this.newList.slice(0, halfLength)
|
|
this.listData2 = this.newList.slice(halfLength)
|
|
})
|
|
})
|
|
},
|
|
getType1Value() {
|
|
const type1Item = this.progressData.find(item => item.type === 1)
|
|
return type1Item ? type1Item.value : 0
|
|
},
|
|
getType2Value() {
|
|
const type2Item = this.progressData.find(item => item.type === 2)
|
|
return type2Item ? type2Item.value : 0
|
|
},
|
|
getType3Value() {
|
|
const type3Item = this.progressData.find(item => item.type === 3)
|
|
return type3Item ? type3Item.value : 0
|
|
},
|
|
getType4Value() {
|
|
const type4Item = this.progressData.find(item => item.type === 4)
|
|
return type4Item ? type4Item.value : 0
|
|
},
|
|
|
|
// 以下生成云标签部分
|
|
// 三角函数角度计算
|
|
sineCosine(a, b, c) {
|
|
this.sa = Math.sin(a * this.dtr)
|
|
this.ca = Math.cos(a * this.dtr)
|
|
this.sb = Math.sin(b * this.dtr)
|
|
this.cb = Math.cos(b * this.dtr)
|
|
this.sc = Math.sin(c * this.dtr)
|
|
this.cc = Math.cos(c * this.dtr)
|
|
},
|
|
// 设置初始定位
|
|
positionAll() {
|
|
this.$nextTick(() => { // 注意: 所有的在onReady方法中执行的方法都需要$nextTick确保所有的标签都已经渲染
|
|
var phi = 0
|
|
var theta = 0
|
|
var max = this.mcList.length
|
|
var aTmp = []
|
|
var oFragment = document.createDocumentFragment()
|
|
// 随机排序
|
|
for (let i = 0; i < this.tagList.length; i++) {
|
|
aTmp.push(this.oA[i])
|
|
}
|
|
aTmp.sort(() => {
|
|
return Math.random() < 0.5 ? 1 : -1
|
|
})
|
|
for (let i = 0; i < aTmp.length; i++) {
|
|
oFragment.appendChild(aTmp[i])
|
|
}
|
|
this.oList.appendChild(oFragment)
|
|
for (let i = 1; i < max + 1; i++) {
|
|
if (this.distr) {
|
|
phi = Math.acos(-1 + (2 * i - 1) / max)
|
|
theta = Math.sqrt(max * Math.PI) * phi
|
|
} else {
|
|
phi = Math.random() * (Math.PI)
|
|
theta = Math.random() * (2 * Math.PI)
|
|
}
|
|
// 坐标变换
|
|
this.mcList[i - 1].cx = this.radius * Math.cos(theta) * Math.sin(phi)
|
|
this.mcList[i - 1].cy = this.radius * Math.sin(theta) * Math.sin(phi)
|
|
this.mcList[i - 1].cz = this.radius * Math.cos(phi)
|
|
this.oA[i - 1].style.left = this.mcList[i - 1].cx + this.oList.offsetWidth / 2 - this.mcList[i - 1].offsetWidth / 2 + 'px'
|
|
this.oA[i - 1].style.top = this.mcList[i - 1].cy + this.oList.offsetHeight / 2 - this.mcList[i - 1].offsetHeight / 2 + 'px'
|
|
}
|
|
})
|
|
},
|
|
// 坐标更新 让标签动起来
|
|
update() {
|
|
this.$nextTick(() => { // 注意: 所有的在onReady方法中执行的方法都需要$nextTick确保所有的标签都已经渲染
|
|
var a
|
|
var b
|
|
// if (this.active) {
|
|
a = (Math.min(Math.max(-this.mouseY, -this.size), this.size) / this.radius) * this.tspeed
|
|
b = (-Math.min(Math.max(-this.mouseX, -this.size), this.size) / this.radius) * this.tspeed
|
|
// } else {
|
|
// a = this.lasta * 0.98
|
|
// b = this.lastb * 0.98
|
|
// }
|
|
this.lasta = a
|
|
this.lastb = b
|
|
if (Math.abs(a) <= 0.01 && Math.abs(b) <= 0.01) {
|
|
return
|
|
}
|
|
var c = 0
|
|
this.sineCosine(a, b, c)
|
|
for (var j = 0; j < this.mcList.length; j++) {
|
|
if (this.mcList[j].on) {
|
|
continue
|
|
}
|
|
var rx1 = this.mcList[j].cx
|
|
var ry1 = this.mcList[j].cy * this.ca + this.mcList[j].cz * (-this.sa)
|
|
var rz1 = this.mcList[j].cy * this.sa + this.mcList[j].cz * this.ca
|
|
var rx2 = rx1 * this.cb + rz1 * this.sb
|
|
var ry2 = ry1
|
|
var rz2 = rx1 * (-this.sb) + rz1 * this.cb
|
|
var rx3 = rx2 * this.cc + ry2 * (-this.sc)
|
|
var ry3 = rx2 * this.sc + ry2 * this.cc
|
|
var rz3 = rz2
|
|
this.mcList[j].cx = rx3
|
|
this.mcList[j].cy = ry3
|
|
this.mcList[j].cz = rz3
|
|
var per = this.d / (this.d + rz3)
|
|
this.mcList[j].x = (this.howElliptical * rx3 * per) - (this.howElliptical * 2)
|
|
this.mcList[j].y = ry3 * per
|
|
this.mcList[j].scale = per
|
|
var alpha = per
|
|
alpha = (alpha - 0.6) * (10 / 6)
|
|
this.mcList[j].alpha = alpha * alpha * alpha - 0.2
|
|
// this.mcList[j].alpha = (this.mcList[j].alpha - 0.6) * (10 / 6)
|
|
this.mcList[j].zIndex = Math.ceil(100 - Math.floor(this.mcList[j].cz))
|
|
}
|
|
this.doPosition()
|
|
this.depthSort()
|
|
})
|
|
},
|
|
//
|
|
doPosition() {
|
|
this.$nextTick(() => { // 注意: 所有的在onReady方法中执行的方法都需要$nextTick确保所有的标签都已经渲染
|
|
var l = this.oList.offsetWidth / 2
|
|
var t = this.oList.offsetHeight / 2
|
|
for (var i = 0; i < this.mcList.length; i++) {
|
|
this.oA[i].style.left = this.mcList[i].cx + l - this.mcList[i].offsetWidth / 2 + 'px'
|
|
this.oA[i].style.top = this.mcList[i].cy + t - this.mcList[i].offsetHeight / 2 + 'px'
|
|
// this.oA[i].style.fontSize = Math.ceil(12 * this.mcList[i].scale / 2) + 8 + 'px'
|
|
this.oA[i].style.filter = 'alpha(opacity=' + 100 * this.mcList[i].alpha + ')'
|
|
this.oA[i].style.opacity = this.mcList[i].alpha
|
|
}
|
|
})
|
|
},
|
|
depthSort() {
|
|
this.$nextTick(() => { // 注意: 所有的在onReady方法中执行的方法都需要$nextTick确保所有的标签都已经渲染
|
|
var aTmp = []
|
|
for (let i = 0; i < this.oA.length; i++) {
|
|
aTmp.push(this.oA[i])
|
|
}
|
|
aTmp.sort(function(vItem1, vItem2) {
|
|
if (vItem1.cz > vItem2.cz) {
|
|
return -1
|
|
} else if (vItem1.cz < vItem2.cz) {
|
|
return 1
|
|
} else {
|
|
return 0
|
|
}
|
|
})
|
|
for (let i = 0; i < aTmp.length; i++) {
|
|
aTmp[i].style.zIndex = i
|
|
}
|
|
})
|
|
},
|
|
onReady() {
|
|
this.$nextTick(() => {
|
|
this.oList = this.$refs.tagcloudall
|
|
this.oA = this.oList.getElementsByTagName('a')
|
|
var oTag = null
|
|
for (var i = 0; i < this.oA.length; i++) {
|
|
oTag = {}
|
|
oTag.offsetWidth = this.oA[i].offsetWidth
|
|
oTag.offsetHeight = this.oA[i].offsetHeight
|
|
this.mcList.push(oTag)
|
|
}
|
|
this.sineCosine(0, 0, 0)
|
|
this.positionAll()
|
|
this.oList.onmouseover = () => {
|
|
this.active = true
|
|
}
|
|
this.oList.onmouseout = () => {
|
|
this.active = false
|
|
}
|
|
// this.oList.onmousemove = (event) => {
|
|
// var oEvent = window.event || event
|
|
|
|
// this.mouseX = oEvent.clientX - (this.oList.offsetLeft + this.oList.offsetWidth / 2)
|
|
// this.mouseY = oEvent.clientY - (this.oList.offsetTop + this.oList.offsetHeight / 2)
|
|
// this.mouseX /= 5
|
|
// this.mouseY /= 5
|
|
// }
|
|
setInterval(() => {
|
|
this.update()
|
|
}, 40) // 定时器执行 不能写setInterval(this.update(), 30)
|
|
})
|
|
}
|
|
}
|
|
}
|
|
|
|
</script>
|
|
|
|
<style lang="scss">
|
|
@import "~@/assets/styles/index.scss";
|
|
@import "~@/assets/styles/font-some.css";
|
|
#tagscloud{
|
|
width:400px;
|
|
height:380px;
|
|
position:relative;
|
|
margin:0 auto;
|
|
}
|
|
|
|
#tagscloud a{
|
|
position:absolute;
|
|
top:0px;
|
|
left:0px;
|
|
line-height:24px;
|
|
text-align:center;
|
|
font-size:18px;
|
|
padding:3px 5px;
|
|
display:inline-block;
|
|
text-wrap: nowrap;
|
|
}
|
|
#tagscloud a.tagc1{
|
|
// border: 1px solid #30ADA6;
|
|
// background-color: #106B66;
|
|
// color: #51EAE2;
|
|
color: #F4C263;
|
|
}
|
|
|
|
#tagscloud a.tagc2{
|
|
font-size: 22px;
|
|
// border: 1px solid #3A64BE;
|
|
// background: rgba(16,45,107,0.7);
|
|
color: #7EA7FF;
|
|
}
|
|
|
|
#tagscloud a.tagc3{
|
|
font-size: 18px;
|
|
// border: 1px solid #9439B6;
|
|
// background: rgba(74,18,95,0.8);
|
|
// color: #CD63F4;
|
|
color: #7EA7FF;
|
|
}
|
|
|
|
#tagscloud a.tagc4{
|
|
font-size: 26px;
|
|
// border: 1px solid #C2943C;
|
|
// background: rgba(107,76,16,0.7);
|
|
color: #F4C263;
|
|
}
|
|
|
|
.tagcloud {
|
|
width: 10rem;
|
|
height: 5rem;
|
|
overflow: hidden;
|
|
p{
|
|
padding: .0625rem;
|
|
border-bottom: 2px dashed rgba(24, 77, 97, 0.5);
|
|
span{
|
|
display: block;
|
|
padding: .075rem 8px;
|
|
white-space: nowrap;
|
|
}
|
|
&.color1{
|
|
border-top: 2px dashed #1F6374;
|
|
border-left: 3px dashed #184D61;
|
|
border-right: 3px dashed #184D61;
|
|
span{
|
|
border: 1px solid #30ADA6;
|
|
background-color: #106B66;
|
|
color: #51EAE2;
|
|
}
|
|
}
|
|
&.color2{
|
|
border-top: 2px dashed #203F7F;
|
|
border-left: 3px dashed #102857;
|
|
border-right: 3px dashed #102857;
|
|
span{
|
|
border: 1px solid #3A64BE;
|
|
background: rgba(16,45,107,0.7);
|
|
color: #7EA7FF;
|
|
}
|
|
}
|
|
&.color3{
|
|
border-top: 2px dashed #613689;
|
|
border-left: 3px dashed #4C2E75;
|
|
border-right: 3px dashed #4C2E75;
|
|
span{
|
|
border: 1px solid #9439B6;
|
|
background: rgba(74,18,95,0.8);
|
|
color: #CD63F4;
|
|
}
|
|
}
|
|
&.color4{
|
|
border-top: 2px dashed #6A5735;
|
|
border-left: 3px dashed #655435;
|
|
border-right: 3px dashed #655435;
|
|
span{
|
|
border: 1px solid #C2943C;
|
|
background: rgba(107,76,16,0.7);
|
|
color: #F4C263;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
.scrollBox{
|
|
flex: 1;
|
|
height: calc(100%);
|
|
box-sizing: border-box;
|
|
margin-left: 0.45rem;
|
|
overflow: hidden;
|
|
.seamless01{
|
|
margin-bottom: .35rem;
|
|
}
|
|
ul{
|
|
display: flex;
|
|
height: 2rem;
|
|
// overflow: hidden;
|
|
li{
|
|
width: 1.375rem;
|
|
height: 2rem;
|
|
margin-right: .7375rem;
|
|
cursor: pointer;
|
|
.bord{
|
|
display: flex;
|
|
flex-wrap: wrap;
|
|
justify-content: space-around;
|
|
align-items: center;
|
|
.book-img{
|
|
width: 1.375rem;
|
|
height: 2rem;
|
|
// background: url('~@/assets/images/book_03.png') no-repeat center center;
|
|
// background-size: contain;
|
|
display: flex;
|
|
align-items: center;
|
|
overflow: hidden;
|
|
img{
|
|
display: block;
|
|
width: 100%;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
</style>
|