63cea824 by 杨炀

init

1 parent dce034b2
<template>
<div class="app-container home">
<el-row class="card">
<el-col :span="6">
<div class="dataItem">
<div>
<p>个人会员</p>
<h2>{{ players }}</h2>
</div>
</div>
</el-col>
<el-col :span="6">
<div class="dataItem">
<div><p>团体会员</p>
<h2>{{ members }}</h2></div>
</div>
</el-col>
<el-col :span="6">
<div class="dataItem">
<div><p>即将到期会员</p>
<h2>{{ soonGuoqiPers }}</h2></div>
</div>
</el-col>
<el-col :span="6">
<div class="dataItem">
<div><p>即将到期团体会员</p>
<h2>{{ soonGuoqiMems }}</h2></div>
</div>
</el-col>
</el-row>
<h3 class="homeTitle">操作流程</h3>
<el-row class="wcard quickbtns" :gutter="20">
<el-col :span="8" @click="router.push('/member/list')">
<a>个人会员</a>
</el-col>
<el-col :span="8" @click="router.push('/group/list1')">
<a>团体会员</a>
</el-col>
<el-col :span="8" @click="router.push('/level/approval')">
<a>级位考试审核</a>
</el-col>
</el-row>
<el-row :gutter="20">
<el-col :span="8">
<h3 class="homeTitle">会员城市分布</h3>
<div class="wcard">
<div id="chart6" style="width: 100%;height: 300px" />
</div>
</el-col>
<el-col :span="8">
<h3 class="homeTitle">会员年龄段分布(人数)</h3>
<div class="wcard">
<div id="chart1" style="width: 100%;height: 300px" />
</div>
</el-col>
<el-col :span="8">
<site-message />
</el-col>
<el-col :span="8">
<h3 class="homeTitle">会员性别分布(人数)</h3>
<div class="wcard">
<div id="chart2" style="width: 100%;height: 300px" />
</div>
</el-col>
<el-col :span="8">
<h3 class="homeTitle">会员级位分布(人数)</h3>
<div class="wcard">
<div id="chart4" style="width: 100%;height: 300px" />
</div>
</el-col>
<el-col :span="8">
<h3 class="homeTitle">会员段位分布(人数)</h3>
<div class="wcard">
<div id="chart5" style="width: 100%;height: 300px" />
</div>
</el-col>
</el-row>
<el-dialog
v-model="dialogVisible"
title=" "
center
width="800px"
:show-close="false"
>
<div>
<span> <el-result style="padding: 0;" icon="warning" title="" /> </span>
</div>
<h1 style="text-align: center;">
会员即将过期,将会影响你的业务办理,请及时续费!
</h1>
<template #footer>
<el-row justify="center">
<el-button type="primary" @click="dialogVisible=false">确定</el-button>
</el-row>
</template>
</el-dialog>
<!-- 已过期 -->
<el-dialog
v-model="ShowDialog"
center
width="800px"
:show-close="false"
>
<div>
<span> <el-result style="padding: 0;" icon="warning" title="" /> </span>
</div>
<h1 style="text-align: center;">
会员已过期,将会影响你的业务办理,请及时续费!
</h1>
<template #footer>
<el-row justify="center">
<el-button type="primary" @click="goBack">确定</el-button>
</el-row>
</template>
</el-dialog>
</div>
</template>
<script setup name="Index">
import * as echarts from 'echarts'
import 'echarts-wordcloud'
import _ from 'lodash'
import { useRouter } from 'vue-router'
import { onMounted, onUnmounted, watch, ref } from 'vue'
import useAppStore from '@/store/modules/app'
import { ageRangeCount, sexRangeCount, levelRangeCount, rankRangeCount, memberCountMap, cityRangeCount } from '@/api/system/homePage'
import SiteMessage from '@/views/index/components/siteMessage'
import useUserStore from '@/store/modules/user'
const userStore = useUserStore()
const appStore = useAppStore()
const myCharts = []
const players = ref(0)
const members = ref(0)
const coach = ref(0)
const examiner = ref(0)
const router = useRouter()
const soonGuoqiPers = ref(0)
const soonGuoqiMems = ref(0)
const dialogVisible = ref(false)
const ShowDialog = ref(false)
onMounted(() => {
if (userStore.authenticationStatus != '2' && userStore.authenticationStatus != '4') {
if (userStore.authenticationStatus == 5) {
ShowDialog.value = true
} else {
perfectInfo()
}
} else {
if (userStore.authenticationStatus == '4') {
dialogVisible.value = true
}
getChart1()
getChart2()
getChart4()
getChart5()
getChart6()
getMemberCount()
window.onresize = _.debounce(myChartsResize, 150)
}
})
onUnmounted(() => {
window.onresize = null
_.each(myCharts, c => c.dispose())
})
// 去续费
function goBack() {
if (userStore.genFlag == 1) {
ShowDialog.value = false
} else {
// 跳转到续费页
router.push({
path: '/user/profile',
query: {
type: 2
}
})
}
}
watch(() => appStore.sidebar.opened, () => {
setTimeout(myChartsResize, 300)
})
function getMemberCount() {
memberCountMap().then(res => {
const map = res.data
players.value = map.players
members.value = map.members
coach.value = map.coach
examiner.value = map.examiner
soonGuoqiPers.value = map.soonExpired
soonGuoqiMems.value = map.soonMember
})
}
function myChartsResize() {
_.each(myCharts, c => c.resize())
}
async function getChart1() {
const result = await ageRangeCount()
const myData = result.data
const myChart = echarts.init(document.getElementById('chart1'))
const option = {
grid: {
left: '0',
right: '0',
bottom: '0',
top: '30',
containLabel: true,
show: true,
backgroundColor: '#fafbfd'
},
tooltip: {
trigger: 'axis'
},
calculable: true,
xAxis: [
{
type: 'category',
data: ['3-6 岁', '7-14 岁', '15-18 岁', '18 岁以上']
}
],
yAxis: [{ type: 'value' }],
series: [
{
name: '会员人数',
type: 'pictorialBar',
symbol: 'roundRect',
symbolSize: [30, 5],
symbolRepeat: true,
symbolClip: false,
itemStyle: {
shadowColor: 'rgba(0, 0, 0, 0.3)',
shadowBlur: 18,
borderColor: '#fff',
borderWidth: 1,
color: {
type: 'linear',
x: 0,
y: 0,
x2: 0,
y2: 1,
colorStops: [{
offset: 0, color: '#0091ea' // 0% 处的颜色
}, {
offset: 1, color: '#36c6e1' // 100% 处的颜色
}],
globalCoord: false // 缺省为 false
}
},
data: myData
}
]
}
myChart.setOption(option)
myCharts.push(myChart)
}
async function getChart2() {
const result = await sexRangeCount()
const myData = result.data
const myChart = echarts.init(document.getElementById('chart2'))
const option = {
color: [
{
type: 'linear',
x: 0,
y: 0,
x2: 0,
y2: 1,
colorStops: [{
offset: 0, color: 'RGBA(57, 160, 221, 1)' // 0% 处的颜色
}, {
offset: 1, color: 'RGBA(61, 147, 223, 1)' // 100% 处的颜色
}],
global: false // 缺省为 false
}, {
type: 'linear',
x: 0,
y: 0,
x2: 0,
y2: 1,
colorStops: [{
offset: 0, color: 'RGBA(240, 96, 153, 1)' // 0% 处的颜色
}, {
offset: 1, color: 'RGBA(252, 101, 122, 1)' // 100% 处的颜色
}],
global: false // 缺省为 false
}
],
tooltip: {
trigger: 'item'
},
legend: {
left: 'right'
},
label: {
formatter: '{d}%',
fontSize: 20,
fontWeight: 'bold'
},
series: [
{
type: 'pie',
radius: ['40%', '70%'],
itemStyle: {
borderColor: '#fff',
borderWidth: 2,
shadowColor: 'rgba(0, 0, 0, 0.2)',
shadowBlur: 20
},
avoidLabelOverlap: false,
data: myData
}
]
}
myChart.setOption(option)
myCharts.push(myChart)
}
async function getChart4() {
const result = await levelRangeCount()
const myData = result.data
const myChart = echarts.init(document.getElementById('chart4'))
const option = {
grid: {
left: '0',
right: '0',
bottom: '0',
top: '30',
containLabel: true,
show: true,
backgroundColor: '#fafbfd'
},
tooltip: {
trigger: 'axis'
},
color: [{
type: 'linear',
x: 0,
y: 0,
x2: 1,
y2: 1,
colorStops: [{
offset: 0, color: '#1DBDCD' // 0% 处的颜色
}, {
offset: 1, color: '#2CE8C7' // 100% 处的颜色
}],
global: false // 缺省为 false
}],
xAxis: { type: 'value' },
yAxis: {
type: 'category',
data: ['一级', '二级', '三级', '四级', '五级', '六级', '七级', '八级', '九级', '十级']
},
series: [{
type: 'bar',
itemStyle: {
borderWidth: 2,
borderColor: '#fff'
},
data: myData
}]
}
myChart.setOption(option)
myCharts.push(myChart)
}
async function getChart5() {
const result = await rankRangeCount()
const myData = result.data
const myChart = echarts.init(document.getElementById('chart5'))
const option = {
grid: {
left: '0',
right: '0',
bottom: '0',
top: '30',
containLabel: true,
show: true,
backgroundColor: '#fafbfd'
},
color: [{
type: 'linear',
x: 0,
y: 0,
x2: 1,
y2: 1,
colorStops: [{
offset: 0, color: '#3DA2DA' // 0% 处的颜色
}, {
offset: 1, color: '#4CC5F8' // 100% 处的颜色
}],
global: false // 缺省为 false
}],
tooltip: {
trigger: 'axis'
},
xAxis: { type: 'value' },
yAxis: {
type: 'category',
data: ['一段', '二段', '三段', '四段', '五段', '六段', '七段', '八段', '九段']
},
series: [{
type: 'bar',
itemStyle: {
borderWidth: 2,
borderColor: '#fff'
},
data: myData
}]
}
myChart.setOption(option)
myCharts.push(myChart)
}
function perfectInfo() {
router.replace({
path: '/perfect'
})
}
async function getChart6() {
const result = await cityRangeCount()
const myData = result.data
const myChart = echarts.init(document.getElementById('chart6'))
const option = {
textStyle: {
color: function() {
return 'rgb(' + [
Math.round(Math.random() * 160),
Math.round(Math.random() * 160),
Math.round(Math.random() * 160)
].join(',') + ')'
}
},
series: [{
type: 'wordCloud',
data: myData
}]
}
myChart.setOption(option)
myCharts.push(myChart)
}
</script>
<style scoped lang="scss">
.card{
background: #FFFFFF;
border-radius: 10px;
}
.dataItem{display: flex;align-items: center;margin:20px 5%;
border-right: 1px solid #eee;
&:last-child{border-right: none;}
img{width: 55px;height: 55px;margin-right: 8%;}
p{font-size: 15px;color: #7B7F83;margin:0 0 10px;}
h2{color: #2B3133;font-size: 1.8vw;margin: 0}
}
.home {
background: RGBA(245, 247, 249, 1);
font-family: "open sans", "Helvetica Neue", Helvetica, Arial, sans-serif;
font-size: 13px;
color: #676a6c;
overflow-x: hidden;
ul {
padding: 0;
margin: 0;list-style-type: none;
}
}
.homeTitle{font-weight: 500;color: #2B3133;margin: 30px 0 15px;}
.fiveflex{display: flex;justify-content: space-between;
.fitem{width: 18%;border-radius: 3px;display: flex;align-items: center; padding: 16px 15px;
p{color: #fff;}
img{margin-right: 20%;}
}
.wcard{width: 18%;border-radius: 10px;}
.ctitle{border-left:2px solid #20C59D;line-height: 1;padding-left: 10px;color: #2B3133;}
.cbody{display: flex;
p{width: 50%;
color: #7B7F83;}
span{display: block;
color: #2B3133;
font-size: 26px;}
}
.wfitem{display: flex; align-items: center;
img{margin-right: 20px; width: 55px;height: 55px;}
p{color: #7B7F83;}
span{display: block;font-size: 26px;color: #2B3133;}
}
}
.fitem:nth-child(1){background: linear-gradient(270deg, #54E1B9, #00CAA6);}
.fitem:nth-child(2){background: linear-gradient(270deg, #BE8EFB, #A76DF4);}
.fitem:nth-child(3){background: linear-gradient(90deg, #FEA449, #FFB95F);}
.fitem:nth-child(4){background: linear-gradient(270deg, #5E9AF3, #4169EC);}
.fitem:nth-child(5){background: linear-gradient(90deg, #F83841, #F76D74);}
.wcard{background: #fff; padding:15px;overflow: hidden;position: relative;
.po-title{position: absolute;
h3{font-size: 18px;color: #2B3133;margin: 0;}
h2{color: #014A9F;font-size: 30px;margin: 6px 0;}
p{color: #7B7F83;font-size: 18px;margin: 0;}
}
}
.quickbtns{
a{display: block;text-align: center;
background: #E5EDF5;
height: 70px;line-height: 70px;text-overflow: ellipsis;
overflow: hidden;white-space: nowrap;
font-size: 20px;margin-bottom: 20px;
color: #014A9F;
border-radius: 10px;
&:hover{color: #FFFFFF;background: #014A9F;}
}
}
.topflex{display: flex;justify-content: space-between;}
.mb40{margin-bottom: 40px;}
@media (max-width: 1400px) {
.quickbtns{
a{ font-size: 18px;}
}
.dataItem{
p { font-size: 14px;}
}
}
@media (max-width: 1200px) {
.quickbtns{
a{ font-size: 16px;}
}
}
</style>
<template>
<div class="app-container home" :hidden="userStore.hasMember == '0'">
<h3 class="homeTitle">操作入口</h3>
<el-row class="wcard quickbtns" :gutter="20">
<el-col :span="5" @click="router.push('/member/addMember')">
<a>添加会员</a>
</el-col>
<el-col :span="5" @click="router.push('/member/memberPay')">
<a>会员缴费</a>
</el-col>
<el-col :span="5" @click="router.push('/member/list')">
<a>会员列表</a>
</el-col>
<el-col :span="5" @click="router.push('/level/apply')">
<a>级位考试申请</a>
</el-col>
<el-col :span="4" @click="router.push('/member/mobillize')">
<a>会员调动</a>
</el-col>
</el-row>
<el-row :gutter="20">
<el-col :span="8">
<h3 class="homeTitle">会员年龄段分布(人数)</h3>
<div class="wcard">
<div id="chart1" style="width: 100%;height: 300px" />
</div>
</el-col>
<el-col :span="8">
<h3 class="homeTitle">会员性别分布(人数)</h3>
<div class="wcard">
<div id="chart2" style="width: 100%;height: 300px" />
</div>
</el-col>
<el-col :span="8">
<h3 class="homeTitle">会员分布</h3>
<div class="wcard">
<div id="chart3" style="width: 100%;height: 300px" />
</div>
</el-col>
<el-col :span="8">
<h3 class="homeTitle">会员级位分布(人数)</h3>
<div class="wcard">
<div id="chart4" style="width: 100%;height: 300px" />
</div>
</el-col>
<el-col :span="8">
<h3 class="homeTitle">会员段位分布(人数)</h3>
<div class="wcard">
<div id="chart5" style="width: 100%;height: 300px" />
</div>
</el-col>
<el-col :span="8">
<site-message />
</el-col>
</el-row>
<el-dialog
v-model="dialogVisible"
center
width="800px"
>
<div>
<span> <el-result style="padding: 0;" icon="warning" title="" /> </span>
</div>
<h1 style="text-align: center;">
{{ title }}
</h1>
<template #footer>
<el-row justify="center">
<el-button type="primary" @click="dialogVisible=false">确定</el-button>
</el-row>
</template>
</el-dialog>
<!-- 已过期 -->
<el-dialog
v-model="ShowDialog"
center
width="800px"
:show-close="false"
>
<div>
<span> <el-result style="padding: 0;" icon="warning" title="" /> </span>
</div>
<h1 style="text-align: center;">
{{ title }}
</h1>
<template #footer>
<el-row justify="center">
<el-button type="primary" @click="goBack">确定</el-button>
</el-row>
</template>
</el-dialog>
</div>
</template>
<script setup name="Index">
import * as echarts from 'echarts'
import _ from 'lodash'
import { onMounted, onUnmounted, watch, ref } from 'vue'
import useAppStore from '@/store/modules/app'
import { useRouter } from 'vue-router'
import useUserStore from '@/store/modules/user'
import { ageRangeCount, sexRangeCount, levelRangeCount, rankRangeCount, clubMemRangeCount } from '@/api/system/homePage'
import SiteMessage from '@/views/index/components/siteMessage'
const userStore = useUserStore()
const router = useRouter()
const title = ref('请先去完善团体信息')
const appStore = useAppStore()
const myCharts = []
const dialogVisible = ref(false)
const ShowDialog = ref(false)
onMounted(() => {
if (userStore.authenticationStatus != '2' && userStore.authenticationStatus != '4') {
if (userStore.authenticationStatus == 5) {
userStore.genFlag != 1 ? title.value = '您的会员已过期,将会影响你的业务办理,请及时续费!' : title.value = '您的会员已过期!'
ShowDialog.value = true
} else {
perfectInfo()
}
} else {
if (userStore.authenticationStatus == '4') {
dialogVisible.value = true
title.value = '你的会员即将过期,将会影响你的业务,请及时续费!'
}
getChart1()
getChart2()
getChart3()
getChart4()
getChart5()
window.onresize = _.debounce(myChartsResize, 150)
}
})
onUnmounted(() => {
window.onresize = null
_.each(myCharts, c => c.dispose())
})
watch(() => appStore.sidebar.opened, () => {
setTimeout(myChartsResize, 300)
})
function myChartsResize() {
_.each(myCharts, c => c.resize())
}
// 去续费
function goBack() {
if (userStore.genFlag == 1) {
ShowDialog.value = false
} else {
// 跳转到续费页
router.push({
path: '/user/profile',
query: {
type: 2
}
})
}
}
async function getChart1() {
const result = await ageRangeCount()
const myData = result.data
const myChart = echarts.init(document.getElementById('chart1'))
const option = {
grid: {
left: '0',
right: '0',
bottom: '0',
top: '30',
containLabel: true,
show: true,
backgroundColor: '#fafbfd'
},
tooltip: {
trigger: 'axis'
},
calculable: true,
xAxis: [
{
type: 'category',
data: ['3-6 岁', '7-14 岁', '15-18 岁', '18 岁以上']
}
],
yAxis: [{ type: 'value' }],
series: [
{
name: '会员人数',
type: 'pictorialBar',
symbol: 'roundRect',
symbolSize: [30, 5],
symbolRepeat: true,
symbolClip: false,
itemStyle: {
shadowColor: 'rgba(0, 0, 0, 0.3)',
shadowBlur: 18,
borderColor: '#fff',
borderWidth: 1,
color: {
type: 'linear',
x: 0,
y: 0,
x2: 0,
y2: 1,
colorStops: [{
offset: 0, color: '#0091ea' // 0% 处的颜色
}, {
offset: 1, color: '#36c6e1' // 100% 处的颜色
}],
globalCoord: false // 缺省为 false
}
},
data: myData
}
]
}
myChart.setOption(option)
myCharts.push(myChart)
}
async function getChart2() {
const result = await sexRangeCount()
const myData = result.data
const myChart = echarts.init(document.getElementById('chart2'))
const option = {
color: [
{
type: 'linear',
x: 0,
y: 0,
x2: 0,
y2: 1,
colorStops: [{
offset: 0, color: 'RGBA(57, 160, 221, 1)' // 0% 处的颜色
}, {
offset: 1, color: 'RGBA(61, 147, 223, 1)' // 100% 处的颜色
}],
global: false // 缺省为 false
}, {
type: 'linear',
x: 0,
y: 0,
x2: 0,
y2: 1,
colorStops: [{
offset: 0, color: 'RGBA(240, 96, 153, 1)' // 0% 处的颜色
}, {
offset: 1, color: 'RGBA(252, 101, 122, 1)' // 100% 处的颜色
}],
global: false // 缺省为 false
}
],
tooltip: {
trigger: 'item'
},
legend: {
left: 'right'
},
label: {
formatter: '{d}%',
fontSize: 20,
fontWeight: 'bold'
},
series: [
{
type: 'pie',
radius: ['40%', '70%'],
itemStyle: {
borderColor: '#fff',
borderWidth: 2,
shadowColor: 'rgba(0, 0, 0, 0.2)',
shadowBlur: 20
},
avoidLabelOverlap: false,
data: myData
}
]
}
myChart.setOption(option)
myCharts.push(myChart)
}
async function getChart3() {
// const myData = [
// { value: 45, name: '有效会员' },
// { value: 20, name: '过期会员' },
// { value: 55, name: '即将过期会员' }
// ]
const res = await clubMemRangeCount()
const myData = res.data
const myChart = echarts.init(document.getElementById('chart3'))
const option = {
color: [
{
type: 'linear',
x: 0,
y: 0,
x2: 0,
y2: 1,
colorStops: [{
offset: 0, color: 'rgb(35,203,203)' // 0% 处的颜色
}, {
offset: 1, color: 'rgb(44,232,199)' // 100% 处的颜色
}],
global: false // 缺省为 false
},
{
type: 'linear',
x: 0,
y: 0,
x2: 0,
y2: 1,
colorStops: [{
offset: 0, color: 'RGBA(57, 160, 221, 1)' // 0% 处的颜色
}, {
offset: 1, color: 'RGBA(61, 147, 223, 1)' // 100% 处的颜色
}],
global: false // 缺省为 false
}, {
type: 'linear',
x: 0,
y: 0,
x2: 0,
y2: 1,
colorStops: [{
offset: 0, color: 'RGBA(240, 96, 153, 1)' // 0% 处的颜色
}, {
offset: 1, color: 'RGBA(252, 101, 122, 1)' // 100% 处的颜色
}],
global: false // 缺省为 false
}
],
tooltip: {
trigger: 'item'
},
legend: {
left: 'right'
},
label: {
formatter: '{d}%',
fontSize: 20,
fontWeight: 'bold'
},
series: [
{
type: 'pie',
radius: ['40%', '70%'],
itemStyle: {
borderColor: '#fff',
borderWidth: 2,
shadowColor: 'rgba(0, 0, 0, 0.2)',
shadowBlur: 20
},
avoidLabelOverlap: false,
data: myData
}
]
}
myChart.setOption(option)
myCharts.push(myChart)
}
async function getChart4() {
const result = await levelRangeCount()
const myData = result.data
const myChart = echarts.init(document.getElementById('chart4'))
const option = {
grid: {
left: '0',
right: '0',
bottom: '0',
top: '30',
containLabel: true,
show: true,
backgroundColor: '#fafbfd'
},
tooltip: {
trigger: 'axis'
},
color: [{
type: 'linear',
x: 0,
y: 0,
x2: 1,
y2: 1,
colorStops: [{
offset: 0, color: '#1DBDCD' // 0% 处的颜色
}, {
offset: 1, color: '#2CE8C7' // 100% 处的颜色
}],
global: false // 缺省为 false
}],
xAxis: { type: 'value' },
yAxis: {
type: 'category',
data: ['一级', '二级', '三级', '四级', '五级', '六级', '七级', '八级', '九级', '十级']
},
series: [{
type: 'bar',
itemStyle: {
borderWidth: 2,
borderColor: '#fff'
},
data: myData
}]
}
myChart.setOption(option)
myCharts.push(myChart)
}
async function getChart5() {
const result = await rankRangeCount()
const myData = result.data
const myChart = echarts.init(document.getElementById('chart5'))
const option = {
grid: {
left: '0',
right: '0',
bottom: '0',
top: '30',
containLabel: true,
show: true,
backgroundColor: '#fafbfd'
},
color: [{
type: 'linear',
x: 0,
y: 0,
x2: 1,
y2: 1,
colorStops: [{
offset: 0, color: '#3DA2DA' // 0% 处的颜色
}, {
offset: 1, color: '#4CC5F8' // 100% 处的颜色
}],
global: false // 缺省为 false
}],
tooltip: {
trigger: 'axis'
},
xAxis: { type: 'value' },
yAxis: {
type: 'category',
data: ['一段', '二段', '三段', '四段', '五段', '六段', '七段', '八段', '九段']
},
series: [{
type: 'bar',
itemStyle: {
borderWidth: 2,
borderColor: '#fff'
},
data: myData
}]
}
myChart.setOption(option)
myCharts.push(myChart)
}
function goUser() {
router.push({
path: '/user/profile'
})
}
function perfectInfo() {
router.replace({
path: '/perfect'
})
}
</script>
<style scoped lang="scss">
.card{
background: #FFFFFF;
border-radius: 10px;
}
.dataItem{display: flex;align-items: center;margin:20px 5%;
border-right: 1px solid #eee;
&:last-child{border-right: none;}
img{width: 55px;height: 55px;margin-right: 8%;}
p{font-size: 15px;color: #7B7F83;margin:0 0 10px;}
h2{color: #2B3133;font-size: 1.8vw;margin: 0}
}
.home {
background: RGBA(245, 247, 249, 1);
font-family: "open sans", "Helvetica Neue", Helvetica, Arial, sans-serif;
font-size: 13px;
color: #676a6c;
overflow-x: hidden;
ul {
padding: 0;
margin: 0;list-style-type: none;
}
}
.homeTitle{font-weight: 500;color: #2B3133;margin: 30px 0 15px;}
.fiveflex{display: flex;justify-content: space-between;
.fitem{width: 18%;border-radius: 3px;display: flex;align-items: center; padding: 16px 15px;
p{color: #fff;}
img{margin-right: 20%;}
}
.wcard{width: 18%;border-radius: 10px;}
.ctitle{border-left:2px solid #20C59D;line-height: 1;padding-left: 10px;color: #2B3133;}
.cbody{display: flex;
p{width: 50%;
color: #7B7F83;}
span{display: block;
color: #2B3133;
font-size: 26px;}
}
.wfitem{display: flex; align-items: center;
img{margin-right: 20px; width: 55px;height: 55px;}
p{color: #7B7F83;}
span{display: block;font-size: 26px;color: #2B3133;}
}
}
.fitem:nth-child(1){background: linear-gradient(270deg, #54E1B9, #00CAA6);}
.fitem:nth-child(2){background: linear-gradient(270deg, #BE8EFB, #A76DF4);}
.fitem:nth-child(3){background: linear-gradient(90deg, #FEA449, #FFB95F);}
.fitem:nth-child(4){background: linear-gradient(270deg, #5E9AF3, #4169EC);}
.fitem:nth-child(5){background: linear-gradient(90deg, #F83841, #F76D74);}
.wcard{background: #fff; padding:15px;overflow: hidden;position: relative;
.po-title{position: absolute;
h3{font-size: 18px;color: #2B3133;margin: 0;}
h2{color: #014A9F;font-size: 30px;margin: 6px 0;}
p{color: #7B7F83;font-size: 18px;margin: 0;}
}
}
.quickbtns{
a{display: block;text-align: center;
background: #E5EDF5;
height: 70px;line-height: 70px;text-overflow: ellipsis;
overflow: hidden;white-space: nowrap;
font-size: 20px;margin-bottom: 20px;
color: #014A9F;
border-radius: 10px;
&:hover{color: #FFFFFF;background: #014A9F;}
}
}
.topflex{display: flex;justify-content: space-between;}
.mb40{margin-bottom: 40px;}
@media (max-width: 1400px) {
.quickbtns{
a{ font-size: 18px;}
}
.dataItem{
p { font-size: 14px;}
}
}
@media (max-width: 1200px) {
.quickbtns{
a{ font-size: 16px;}
}
}
</style>
<template>
<div>
<h3 class="homeTitle">待办提醒<router-link class="fr" to="/messages">更多<el-icon><ArrowRight /></el-icon></router-link></h3>
<div class="wcard">
<ul class="mesUl" :style="`height: ${mesHeight}px`">
<li v-for="item in messageList" :key="item.id" :class="{'done':item.readFlag=='1'}" @click="readMessage(item)">
<div>{{ item.name }}</div>
<span class="date">{{ parseTime(item.createTime,'{m}-{d} {h}:{i}') }}</span>
</li>
<li v-if="messageList?.length<=0" class="done">
暂无代办业务!
</li>
</ul>
</div>
</div>
</template>
<script setup>
import { onMounted, ref } from 'vue'
import { getMessage, reader } from '@/api/system/homePage'
import _ from 'lodash'
import { useRouter } from 'vue-router'
const router = useRouter()
const messageList = ref([])
defineProps({
mesHeight: {
type: Number,
default: 300
}
})
onMounted(() => {
getMessageList()
})
async function getMessageList() {
const res = await getMessage({
pageNum: 1,
pageSize: 10
})
_.each(res.rows, (d) => {
switch (d.type) {
case 30001:
d.name = '你有一条会员缴费等待审批,点击去处理!'
d.path = '/member/audit'
break
case 30002:
d.name = '你有一条级位考试等待审批,点击去处理!'
d.path = '/level/approval'
break
case 30003:
d.name = '你有一条段位考试等待审批,点击去处理!'
d.path = '/rank/approval'
break
case 30004:
d.name = '你有一条会员调动等待审批,点击去处理!'
d.path = '/member/mobillize'
break
case 30005:
d.name = '你有一条团体会员认证等待审批,点击去处理!'
d.path = '/group/authentication'
break
case 30006:
d.name = '你有一条段位成绩等待审批,点击去处理!'
d.path = '/rank/score/approval'
break
case 40001:
d.name = '你有一条级位申请待提交,点击去处理!'
d.path = '/level/apply/modify/' + d.eventId
break
case 40002:
d.name = '你有一条段位申请待提交,点击去处理!'
d.path = '/rank/apply/modify/' + d.eventId
break
case 40003:
d.name = '你有一条成绩维护的数据待提交,点击去处理!'
d.path = '/rank/score/modify/' + d.eventId
break
case 50001:
d.name = '你有一条新的个人会员申请,点击去处理!'
d.path = '/member/list'
break
}
})
messageList.value = res.rows
}
async function readMessage(item) {
await router.push(item.path)
await reader({ id: item.id })
item.readFlag = '1'
}
</script>
<style scoped lang="scss">
.homeTitle{font-weight: 500;color: #2B3133;margin: 30px 0 15px;}
.wcard{background: #fff; padding:15px;overflow: hidden;position: relative;
.po-title{position: absolute;
h3{font-size: 18px;color: #2B3133;margin: 0;}
h2{color: #014A9F;font-size: 30px;margin: 6px 0;}
p{color: #7B7F83;font-size: 18px;margin: 0;}
}
}
.home {
background: RGBA(245, 247, 249, 1);
font-family: "open sans", "Helvetica Neue", Helvetica, Arial, sans-serif;
font-size: 13px;
color: #676a6c;
overflow-x: hidden;
ul {
padding: 0;
margin: 0;list-style-type: none;
}
}
.mesUl{
overflow: auto;
li{ position: relative;line-height: 45px;padding-left: 40px;display: flex;justify-content: space-between;
color: #666;cursor: pointer;
&>div{width: 80%;overflow: hidden;text-overflow: ellipsis;white-space: nowrap; font-size: 16px;}
&:before{width: 6px;content: '';
height: 6px;position: absolute;left: 20px;top: 0;bottom: 0;margin: auto;
background: var(--el-color-primary);
border-radius: 50%;}
&:hover{background: #f4f4f4;}
.link{display: inline-block;}
.date{font-size: 12px;float: right;color: #999;width: 20%;text-align: right;padding-right: 15px; min-width: 80px}
}
li.done{&:before{background: #ddd;}}
}
</style>
<template>
<div class="app-container">
<div class="wcard">
<ul class="mesUl">
<li v-for="item in messageList" :key="item.id" :class="{'done':item.readFlag=='1'}" @click="readMessage(item)">
<div>{{ item.name }}</div>
<span class="date">{{ item.createTime }}</span>
</li>
<li v-if="messageList.length<=0" class="done">
暂无代办业务!
</li>
</ul>
<pagination
v-show="total > 0"
v-model:page="queryParams.pageNum"
v-model:limit="queryParams.pageSize"
:page-sizes="[15,30,45,60]"
:total="total"
@pagination="getMessageList"
/>
</div>
</div>
</template>
<script setup name="Messages">
import { onMounted, reactive, ref } from 'vue'
import { getMessage, reader } from '@/api/system/homePage'
import _ from 'lodash'
import { useRouter } from 'vue-router'
const router = useRouter()
const messageList = ref([])
const queryParams = reactive({
pageNum: 1,
pageSize: 10
})
const total = ref(0)
onMounted(() => {
getMessageList()
})
async function getMessageList() {
const res = await getMessage(queryParams)
_.each(res.rows, (d) => {
switch (d.type) {
case 30001:
d.name = '你有一条会员缴费等待审批,点击去处理!'
d.path = '/member/audit'
break
case 30002:
d.name = '你有一条级位考试等待审批,点击去处理!'
d.path = '/level/approval'
break
case 30003:
d.name = '你有一条段位考试等待审批,点击去处理!'
d.path = '/rank/approval'
break
case 30004:
d.name = '你有一条会员调动等待审批,点击去处理!'
d.path = '/member/mobillize'
break
case 30005:
d.name = '你有一条团体会员认证等待审批,点击去处理!'
d.path = '/member/audit'
break
case 30006:
d.name = '你有一条段位成绩等待审批,点击去处理!'
d.path = '/rank/score/approval'
break
case 40001:
d.name = '你有一条级位申请待提交,点击去处理!'
d.path = '/level/apply/modify/:examId'
break
case 40002:
d.name = '你有一条段位位申请待提交,点击去处理!'
d.path = '/rank/apply/modify/:examId'
break
}
})
messageList.value = res.rows
total.value = res.total
}
async function readMessage(item) {
await router.push(item.path)
await reader({ id: item.id })
item.readFlag = '1'
}
</script>
<style scoped lang="scss">
.wcard{background: #fff; padding:15px;overflow: hidden;position: relative;
.po-title{position: absolute;
h3{font-size: 18px;color: #2B3133;margin: 0;}
h2{color: #014A9F;font-size: 30px;margin: 6px 0;}
p{color: #7B7F83;font-size: 18px;margin: 0;}
}
}
.mesUl{
li{ position: relative;line-height: 45px;padding-left: 40px;display: flex;justify-content: space-between;
color: #666;cursor: pointer;
&>div{width: 80%;overflow: hidden;text-overflow: ellipsis;white-space: nowrap; font-size: 16px;}
&:before{width: 6px;content: '';
height: 6px;position: absolute;left: 20px;top: 0;bottom: 0;margin: auto;
background: var(--el-color-primary);
border-radius: 50%;}
&:hover{background: #f4f4f4;}
.link{display: inline-block;}
.date{font-size: 12px;float: right;color: #999;width: 20%;text-align: right;padding-right: 15px;}
}
li.done{&:before{background: #f4f4f4;}}
}
</style>
<template>
<div class="app-container home">
<el-row class="card">
<el-col :span="5">
<div class="dataItem">
<div>
<p>个人会员</p>
<h2>{{ players }}</h2>
</div>
</div>
</el-col>
<el-col :span="5">
<div class="dataItem">
<div><p>团体会员</p>
<h2>{{ members }}</h2></div>
</div>
</el-col>
<el-col :span="5">
<div class="dataItem">
<div><p>二级协会</p>
<h2>{{ secondMembers }}</h2></div>
</div>
</el-col>
<el-col :span="5">
<div class="dataItem">
<div><p>即将到期会员</p>
<h2>{{ soonGuoqiPers }}</h2></div>
</div>
</el-col>
<el-col :span="4">
<div class="dataItem">
<div><p>即将到期团体会员</p>
<h2>{{ soonGuoqiMems }}</h2></div>
</div>
</el-col>
</el-row>
<h3 class="homeTitle">操作流程</h3>
<el-row class="wcard quickbtns" :gutter="20">
<el-col :span="5" @click="router.push('/member/audit')">
<a>缴费审核</a>
</el-col>
<el-col :span="5" @click="router.push('/level/approval')">
<a>级位考试审核</a>
</el-col>
<el-col :span="5" @click="router.push('/rank/apply')">
<a>段位考试申请</a>
</el-col>
<el-col :span="5" @click="router.push('/level/download')">
<a>级位考试证书确认</a>
</el-col>
<el-col :span="4" @click="router.push('/rank/download')">
<a>段位考试证书确认</a>
</el-col>
</el-row>
<el-row :gutter="20">
<el-col :span="8">
<h3 class="homeTitle">会员城市分布</h3>
<div class="wcard">
<div id="chart6" style="width: 100%;height: 300px" />
</div>
</el-col>
<el-col :span="8">
<h3 class="homeTitle">会员年龄段分布(人数)</h3>
<div class="wcard">
<div id="chart1" style="width: 100%;height: 300px" />
</div>
</el-col>
<el-col :span="8">
<site-message />
</el-col>
<el-col :span="8">
<h3 class="homeTitle">会员性别分布(人数)</h3>
<div class="wcard">
<div id="chart2" style="width: 100%;height: 300px" />
</div>
</el-col>
<el-col :span="8">
<h3 class="homeTitle">会员级位分布(人数)</h3>
<div class="wcard">
<div id="chart4" style="width: 100%;height: 300px" />
</div>
</el-col>
<el-col :span="8">
<h3 class="homeTitle">会员段位分布(人数)</h3>
<div class="wcard">
<div id="chart5" style="width: 100%;height: 300px" />
</div>
</el-col>
</el-row>
<el-dialog
v-model="dialogVisible"
center
width="800px"
:show-close="false"
>
<div>
<span> <el-result style="padding: 0;" icon="warning" title="" /> </span>
</div>
<h1 style="text-align: center;">
会员即将过期,将会影响你的业务办理,请及时续费!
</h1>
<template #footer>
<el-row justify="center">
<el-button type="primary" @click="dialogVisible=false">确定</el-button>
</el-row>
</template>
</el-dialog>
<!-- 已过期 -->
<el-dialog
v-model="ShowDialog"
center
width="800px"
:show-close="false"
>
<div>
<span> <el-result style="padding: 0;" icon="warning" title="" /> </span>
</div>
<h1 style="text-align: center;">
会员已过期,将会影响你的业务办理,请及时续费!
</h1>
<template #footer>
<el-row justify="center">
<el-button type="primary" @click="goBack">确定</el-button>
</el-row>
</template>
</el-dialog>
</div>
</template>
<script setup name="Index">
import * as echarts from 'echarts'
import 'echarts-wordcloud'
import _ from 'lodash'
import { useRouter } from 'vue-router'
import { onMounted, onUnmounted, watch, ref } from 'vue'
import useAppStore from '@/store/modules/app'
import { ageRangeCount, sexRangeCount, levelRangeCount, rankRangeCount, cityRangeCount, memberCountMap } from '@/api/system/homePage'
import SiteMessage from '@/views/index/components/siteMessage'
import useUserStore from '@/store/modules/user'
const userStore = useUserStore()
const router = useRouter()
const appStore = useAppStore()
const myCharts = []
const players = ref(0)
const members = ref(0)
const coach = ref(0)
const examiner = ref(0)
const soonGuoqiPers = ref(0)
const soonGuoqiMems = ref(0)
const secondMembers = ref(0)
const dialogVisible = ref(false)
const ShowDialog = ref(false)
onMounted(() => {
if (userStore.authenticationStatus != '2' && userStore.authenticationStatus != '4') {
if (userStore.authenticationStatus == 5) {
ShowDialog.value = true
} else {
perfectInfo()
}
} else {
if (userStore.authenticationStatus == '4') {
dialogVisible.value = true
}
getChart1()
getChart2()
getChart4()
getChart5()
getChart6()
getMemberCount()
window.onresize = _.debounce(myChartsResize, 150)
}
})
// 去续费
function goBack() {
if (userStore.genFlag == 1) {
ShowDialog.value = false
} else {
// 跳转到续费页
router.push({
path: '/user/profile',
query: {
type: 2
}
})
}
}
function perfectInfo() {
router.replace({
path: '/perfect'
})
}
onUnmounted(() => {
window.onresize = null
_.each(myCharts, c => c.dispose())
})
watch(() => appStore.sidebar.opened, () => {
setTimeout(myChartsResize, 300)
})
function getMemberCount() {
memberCountMap().then(res => {
const map = res.data
players.value = map.players
members.value = map.members
coach.value = map.coach
examiner.value = map.examiner
soonGuoqiPers.value = map.soonExpired
soonGuoqiMems.value = map.soonMember
secondMembers.value = map.secondMember
})
}
function myChartsResize() {
_.each(myCharts, c => c.resize())
}
async function getChart1() {
const result = await ageRangeCount()
const myData = result.data
const myChart = echarts.init(document.getElementById('chart1'))
const option = {
grid: {
left: '0',
right: '0',
bottom: '0',
top: '30',
containLabel: true,
show: true,
backgroundColor: '#fafbfd'
},
tooltip: {
trigger: 'axis'
},
calculable: true,
xAxis: [
{
type: 'category',
data: ['3-6 岁', '7-14 岁', '15-18 岁', '18 岁以上']
}
],
yAxis: [{ type: 'value' }],
series: [
{
name: '会员人数',
type: 'pictorialBar',
symbol: 'roundRect',
symbolSize: [30, 5],
symbolRepeat: true,
symbolClip: false,
itemStyle: {
shadowColor: 'rgba(0, 0, 0, 0.3)',
shadowBlur: 18,
borderColor: '#fff',
borderWidth: 1,
color: {
type: 'linear',
x: 0,
y: 0,
x2: 0,
y2: 1,
colorStops: [{
offset: 0, color: '#0091ea' // 0% 处的颜色
}, {
offset: 1, color: '#36c6e1' // 100% 处的颜色
}],
globalCoord: false // 缺省为 false
}
},
data: myData
}
]
}
myChart.setOption(option)
myCharts.push(myChart)
}
async function getChart2() {
// const myData = [
// { value: 45, name: '男' },
// { value: 55, name: '女' }
// ]
const result = await sexRangeCount()
const myData = result.data
const myChart = echarts.init(document.getElementById('chart2'))
const option = {
color: [
{
type: 'linear',
x: 0,
y: 0,
x2: 0,
y2: 1,
colorStops: [{
offset: 0, color: 'RGBA(57, 160, 221, 1)' // 0% 处的颜色
}, {
offset: 1, color: 'RGBA(61, 147, 223, 1)' // 100% 处的颜色
}],
global: false // 缺省为 false
}, {
type: 'linear',
x: 0,
y: 0,
x2: 0,
y2: 1,
colorStops: [{
offset: 0, color: 'RGBA(240, 96, 153, 1)' // 0% 处的颜色
}, {
offset: 1, color: 'RGBA(252, 101, 122, 1)' // 100% 处的颜色
}],
global: false // 缺省为 false
}
],
tooltip: {
trigger: 'item'
},
legend: {
left: 'right'
},
label: {
formatter: '{d}%',
fontSize: 20,
fontWeight: 'bold'
},
series: [
{
type: 'pie',
radius: ['40%', '70%'],
itemStyle: {
borderColor: '#fff',
borderWidth: 2,
shadowColor: 'rgba(0, 0, 0, 0.2)',
shadowBlur: 20
},
avoidLabelOverlap: false,
data: myData
}
]
}
myChart.setOption(option)
myCharts.push(myChart)
}
async function getChart4() {
const result = await levelRangeCount()
const myData = result.data
const myChart = echarts.init(document.getElementById('chart4'))
const option = {
grid: {
left: '0',
right: '0',
bottom: '0',
top: '30',
containLabel: true,
show: true,
backgroundColor: '#fafbfd'
},
tooltip: {
trigger: 'axis'
},
color: [{
type: 'linear',
x: 0,
y: 0,
x2: 1,
y2: 1,
colorStops: [{
offset: 0, color: '#1DBDCD' // 0% 处的颜色
}, {
offset: 1, color: '#2CE8C7' // 100% 处的颜色
}],
global: false // 缺省为 false
}],
xAxis: { type: 'value' },
yAxis: {
type: 'category',
data: ['一级', '二级', '三级', '四级', '五级', '六级', '七级', '八级', '九级', '十级']
},
series: [{
type: 'bar',
itemStyle: {
borderWidth: 2,
borderColor: '#fff'
},
data: myData
}]
}
myChart.setOption(option)
myCharts.push(myChart)
}
async function getChart5() {
const result = await rankRangeCount()
const myData = result.data
const myChart = echarts.init(document.getElementById('chart5'))
const option = {
grid: {
left: '0',
right: '0',
bottom: '0',
top: '30',
containLabel: true,
show: true,
backgroundColor: '#fafbfd'
},
color: [{
type: 'linear',
x: 0,
y: 0,
x2: 1,
y2: 1,
colorStops: [{
offset: 0, color: '#3DA2DA' // 0% 处的颜色
}, {
offset: 1, color: '#4CC5F8' // 100% 处的颜色
}],
global: false // 缺省为 false
}],
tooltip: {
trigger: 'axis'
},
xAxis: { type: 'value' },
yAxis: {
type: 'category',
data: ['一段', '二段', '三段', '四段', '五段', '六段', '七段', '八段', '九段']
},
series: [{
type: 'bar',
itemStyle: {
borderWidth: 2,
borderColor: '#fff'
},
data: myData
}]
}
myChart.setOption(option)
myCharts.push(myChart)
}
async function getChart6() {
const result = await cityRangeCount()
const myData = result.data
const myChart = echarts.init(document.getElementById('chart6'))
const option = {
textStyle: {
color: function() {
return 'rgb(' + [
Math.round(Math.random() * 160),
Math.round(Math.random() * 160),
Math.round(Math.random() * 160)
].join(',') + ')'
}
},
series: [{
type: 'wordCloud',
data: myData
}]
}
myChart.setOption(option)
myCharts.push(myChart)
}
</script>
<style scoped lang="scss">
.card{
background: #FFFFFF;
border-radius: 10px;
}
.dataItem{display: flex;align-items: center;margin:20px 5%;
border-right: 1px solid #eee;
&:last-child{border-right: none;}
img{width: 55px;height: 55px;margin-right: 8%;}
p{font-size: 15px;color: #7B7F83;margin:0 0 10px;}
h2{color: #2B3133;font-size: 1.8vw;margin: 0}
}
.home {
background: RGBA(245, 247, 249, 1);
font-family: "open sans", "Helvetica Neue", Helvetica, Arial, sans-serif;
font-size: 13px;
color: #676a6c;
overflow-x: hidden;
ul {
padding: 0;
margin: 0;list-style-type: none;
}
}
.homeTitle{font-weight: 500;color: #2B3133;margin: 30px 0 15px;}
.fiveflex{display: flex;justify-content: space-between;
.fitem{width: 18%;border-radius: 3px;display: flex;align-items: center; padding: 16px 15px;
p{color: #fff;}
img{margin-right: 20%;}
}
.wcard{width: 18%;border-radius: 10px;}
.ctitle{border-left:2px solid #20C59D;line-height: 1;padding-left: 10px;color: #2B3133;}
.cbody{display: flex;
p{width: 50%;
color: #7B7F83;}
span{display: block;
color: #2B3133;
font-size: 26px;}
}
.wfitem{display: flex; align-items: center;
img{margin-right: 20px; width: 55px;height: 55px;}
p{color: #7B7F83;}
span{display: block;font-size: 26px;color: #2B3133;}
}
}
.fitem:nth-child(1){background: linear-gradient(270deg, #54E1B9, #00CAA6);}
.fitem:nth-child(2){background: linear-gradient(270deg, #BE8EFB, #A76DF4);}
.fitem:nth-child(3){background: linear-gradient(90deg, #FEA449, #FFB95F);}
.fitem:nth-child(4){background: linear-gradient(270deg, #5E9AF3, #4169EC);}
.fitem:nth-child(5){background: linear-gradient(90deg, #F83841, #F76D74);}
.wcard{background: #fff; padding:15px;overflow: hidden;position: relative;
.po-title{position: absolute;
h3{font-size: 18px;color: #2B3133;margin: 0;}
h2{color: #014A9F;font-size: 30px;margin: 6px 0;}
p{color: #7B7F83;font-size: 18px;margin: 0;}
}
}
.quickbtns{
a{display: block;text-align: center;
background: #E5EDF5;
height: 70px;line-height: 70px;text-overflow: ellipsis;
overflow: hidden;white-space: nowrap;
font-size: 20px;margin-bottom: 20px;
color: #014A9F;
border-radius: 10px;
&:hover{color: #FFFFFF;background: #014A9F;}
}
}
.topflex{display: flex;justify-content: space-between;}
.mb40{margin-bottom: 40px;}
@media (max-width: 1400px) {
.quickbtns{
a{ font-size: 18px;}
}
.dataItem{
p { font-size: 14px;}
}
}
@media (max-width: 1200px) {
.quickbtns{
a{ font-size: 16px;}
}
}
</style>
<template>
<div class="app-container home">
<el-row class="card">
<el-col :span="4">
<div class="dataItem">
<div>
<p>个人会员</p>
<h2>{{ players }}</h2>
</div>
</div>
</el-col>
<el-col :span="4">
<div class="dataItem">
<div><p>团体会员</p>
<h2>{{ members }}</h2></div>
</div>
</el-col>
<el-col :span="4">
<div class="dataItem">
<div><p>教练</p>
<h2>{{ coach }}</h2></div>
</div>
</el-col>
<el-col :span="4">
<div class="dataItem">
<div><p>考官</p>
<h2>{{ examiner }}</h2></div>
</div>
</el-col>
<el-col :span="4">
<div class="dataItem">
<div><p>即将到期会员</p>
<h2>{{ soonGuoqiPers }}</h2></div>
</div>
</el-col>
<el-col :span="4">
<div class="dataItem">
<div><p>即将到期团体会员</p>
<h2>{{ soonGuoqiMems }}</h2></div>
</div>
</el-col>
</el-row>
<el-row :gutter="20">
<el-col :span="12">
<h3 class="homeTitle">操作流程</h3>
<el-row class="wcard quickbtns" :gutter="20">
<el-col :span="8" @click="router.push('/system/user')">
<a>用户管理</a>
</el-col>
<el-col :span="8" @click="router.push('/system/config/config')">
<a>参数配置</a>
</el-col>
<el-col :span="8" @click="router.push('/member/mobillize')">
<a>会员调动审核</a>
</el-col>
<el-col :span="8" @click="router.push('/member/audit')">
<a>缴费审核</a>
</el-col>
<el-col :span="8" @click="router.push('/member/feeBill')">
<a>缴费单记录</a>
</el-col>
<el-col :span="8" @click="router.push('/level/approval')">
<a>级位考试审核</a>
</el-col>
<el-col :span="8" @click="router.push('/level/cert')">
<a>级位考试证书发放</a>
</el-col>
<el-col :span="8" @click="router.push('/rank/approval')">
<a>段位考试审核</a>
</el-col>
<el-col :span="8" @click="router.push('/rank/cert')">
<a>段位考试证书发放</a>
</el-col>
</el-row>
</el-col>
<el-col :span="12">
<site-message :mes-height="270" />
</el-col>
</el-row>
<el-row :gutter="20">
<el-col :span="8">
<h3 class="homeTitle">会员年龄段分布(人数)</h3>
<div class="wcard">
<div id="chart1" style="width: 100%;height: 300px" />
</div>
</el-col>
<el-col :span="8">
<h3 class="homeTitle">会员性别分布(人数)</h3>
<div class="wcard">
<div id="chart2" style="width: 100%;height: 300px" />
</div>
</el-col>
<el-col :span="8">
<h3 class="homeTitle">各省会员数量</h3>
<div class="wcard">
<div class="po-title">
<!-- <h3>江苏省跆拳道协会</h3>-->
<!-- <h2>2300</h2>-->
<p>会员数</p>
</div>
<div id="chart3" style="width: 100%;height: 300px" />
</div>
</el-col>
<el-col :span="8">
<h3 class="homeTitle">会员级位分布(人数)</h3>
<div class="wcard">
<div id="chart4" style="width: 100%;height: 300px" />
</div>
</el-col>
<el-col :span="8">
<h3 class="homeTitle">会员段位分布(人数)</h3>
<div class="wcard">
<div id="chart5" style="width: 100%;height: 300px" />
</div>
</el-col>
<el-col :span="8">
<h3 class="homeTitle">会员城市分布</h3>
<div class="wcard">
<div id="chart6" style="width: 100%;height: 300px" />
</div>
</el-col>
</el-row>
</div>
</template>
<script setup name="Index">
import * as echarts from 'echarts'
import chinaMap from '@/assets/json/china.json'
import 'echarts-wordcloud'
import _ from 'lodash'
import { onMounted, onUnmounted, watch, ref } from 'vue'
import useAppStore from '@/store/modules/app'
import { useRouter } from 'vue-router'
import { ageRangeCount, sexRangeCount, levelRangeCount, rankRangeCount, provinceRangeCount, cityRangeCount, memberCountMap } from '@/api/system/homePage'
import SiteMessage from '@/views/index/components/siteMessage'
const router = useRouter()
const appStore = useAppStore()
const myCharts = []
const players = ref(0)
const members = ref(0)
const coach = ref(0)
const examiner = ref(0)
const soonGuoqiPers = ref(0)
const soonGuoqiMems = ref(0)
onMounted(() => {
getChart1()
getChart2()
getChart3()
getChart4()
getChart5()
getChart6()
getMemberCount()
window.onresize = _.debounce(myChartsResize, 150)
})
onUnmounted(() => {
window.onresize = null
_.each(myCharts, c => c.dispose())
})
watch(() => appStore.sidebar.opened, () => {
setTimeout(myChartsResize, 300)
})
function myChartsResize() {
_.each(myCharts, c => c.resize())
}
function getMemberCount() {
memberCountMap().then(res => {
const map = res.data
players.value = map.players
members.value = map.members
coach.value = map.coach
examiner.value = map.examiner
soonGuoqiPers.value = map.soonExpired
soonGuoqiMems.value = map.soonMember
})
}
async function getChart1() {
const result = await ageRangeCount()
const myData = result.data
const myChart = echarts.init(document.getElementById('chart1'))
const option = {
grid: {
left: '0',
right: '0',
bottom: '0',
top: '30',
containLabel: true,
show: true,
backgroundColor: '#fafbfd'
},
tooltip: {
trigger: 'axis'
},
calculable: true,
xAxis: [
{
type: 'category',
data: ['3-6 岁', '7-14 岁', '15-18 岁', '18 岁以上']
}
],
yAxis: [{ type: 'value' }],
series: [
{
name: '会员人数',
type: 'pictorialBar',
symbol: 'roundRect',
symbolSize: [30, 5],
symbolRepeat: true,
symbolClip: false,
itemStyle: {
shadowColor: 'rgba(0, 0, 0, 0.3)',
shadowBlur: 18,
borderColor: '#fff',
borderWidth: 1,
color: {
type: 'linear',
x: 0,
y: 0,
x2: 0,
y2: 1,
colorStops: [{
offset: 0, color: '#0091ea' // 0% 处的颜色
}, {
offset: 1, color: '#36c6e1' // 100% 处的颜色
}],
globalCoord: false // 缺省为 false
}
},
data: myData
}
]
}
myChart.setOption(option)
myCharts.push(myChart)
}
async function getChart2() {
// const myData = [
// { value: 45, name: '男' },
// { value: 55, name: '女' }
// ]
const result = await sexRangeCount()
const myData = result.data
const myChart = echarts.init(document.getElementById('chart2'))
const option = {
color: [
{
type: 'linear',
x: 0,
y: 0,
x2: 0,
y2: 1,
colorStops: [{
offset: 0, color: 'RGBA(57, 160, 221, 1)' // 0% 处的颜色
}, {
offset: 1, color: 'RGBA(61, 147, 223, 1)' // 100% 处的颜色
}],
global: false // 缺省为 false
}, {
type: 'linear',
x: 0,
y: 0,
x2: 0,
y2: 1,
colorStops: [{
offset: 0, color: 'RGBA(240, 96, 153, 1)' // 0% 处的颜色
}, {
offset: 1, color: 'RGBA(252, 101, 122, 1)' // 100% 处的颜色
}],
global: false // 缺省为 false
}
],
tooltip: {
trigger: 'item'
},
legend: {
left: 'right'
},
label: {
formatter: '{d}%',
fontSize: 20,
fontWeight: 'bold'
},
series: [
{
type: 'pie',
radius: ['40%', '70%'],
itemStyle: {
borderColor: '#fff',
borderWidth: 2,
shadowColor: 'rgba(0, 0, 0, 0.2)',
shadowBlur: 20
},
avoidLabelOverlap: false,
data: myData
}
]
}
myChart.setOption(option)
myCharts.push(myChart)
}
async function getChart3() {
// const myData = [
// {
// name: '北京市',
// value: 1100
// },
// {
// name: '上海市',
// value: 400
// },
// {
// name: '江苏省',
// value: 300
// },
// {
// name: '广东省',
// value: 200
// }
// ]
const result = await provinceRangeCount()
const myData = result.data
const myChart = echarts.init(document.getElementById('chart3'))
echarts.registerMap('china', chinaMap)
const option = {
tooltip: {
trigger: 'item',
// formatter: '{b}:{c}'
formatter: (params, ticket, callback) => {
return `${params.name}${params.value || 0}`
}
},
visualMap: {
type: 'continuous',
min: 0,
max: Math.max(1000, (_.maxBy(myData, item => item.value)?.value || 0)),
calculable: true,
// itemWidth: 20,
// itemHeight: 140,
text: ['高', '低'],
inRange: {
color: ['#A1D0FF', '#63B0FF', '#3D9BFF', '#158DED', '#1A7FCB']
}
},
series: [
{
type: 'map',
map: 'china',
roam: true,
zoom: 1.5,
top: '25%',
label: {
show: false
},
itemStyle: {
borderColor: '#fff'
},
emphasis: {
itemStyle: {
areaColor: '#FABD47'
}
},
data: myData
}
]
}
myChart.setOption(option)
myCharts.push(myChart)
}
async function getChart4() {
// const myData = [120, 210, 150, 80, 20, 30, 40, 50, 60, 80]
const result = await levelRangeCount()
const myData = result.data
const myChart = echarts.init(document.getElementById('chart4'))
const option = {
grid: {
left: '0',
right: '0',
bottom: '0',
top: '30',
containLabel: true,
show: true,
backgroundColor: '#fafbfd'
},
tooltip: {
trigger: 'axis'
},
color: [{
type: 'linear',
x: 0,
y: 0,
x2: 1,
y2: 1,
colorStops: [{
offset: 0, color: '#1DBDCD' // 0% 处的颜色
}, {
offset: 1, color: '#2CE8C7' // 100% 处的颜色
}],
global: false // 缺省为 false
}],
xAxis: { type: 'value' },
yAxis: {
type: 'category',
data: ['一级', '二级', '三级', '四级', '五级', '六级', '七级', '八级', '九级', '十级']
},
series: [{
type: 'bar',
itemStyle: {
borderWidth: 2,
borderColor: '#fff'
},
data: myData
}]
}
myChart.setOption(option)
myCharts.push(myChart)
}
async function getChart5() {
// const myData = [120, 210, 150, 80, 20, 30, 40, 50, 60]
const result = await rankRangeCount()
const myData = result.data
const myChart = echarts.init(document.getElementById('chart5'))
const option = {
grid: {
left: '0',
right: '0',
bottom: '0',
top: '30',
containLabel: true,
show: true,
backgroundColor: '#fafbfd'
},
color: [{
type: 'linear',
x: 0,
y: 0,
x2: 1,
y2: 1,
colorStops: [{
offset: 0, color: '#3DA2DA' // 0% 处的颜色
}, {
offset: 1, color: '#4CC5F8' // 100% 处的颜色
}],
global: false // 缺省为 false
}],
tooltip: {
trigger: 'axis'
},
xAxis: { type: 'value' },
yAxis: {
type: 'category',
data: ['一段', '二段', '三段', '四段', '五段', '六段', '七段', '八段', '九段']
},
series: [{
type: 'bar',
itemStyle: {
borderWidth: 2,
borderColor: '#fff'
},
data: myData
}]
}
myChart.setOption(option)
myCharts.push(myChart)
}
async function getChart6() {
// const myData = [
// {
// name: '北京市',
// value: 1100
// },
// {
// name: '上海市',
// value: 400
// },
// {
// name: '江苏省',
// value: 300
// },
// {
// name: '广东省',
// value: 2000
// }
// ]
const result = await cityRangeCount()
const myData = result.data
const myChart = echarts.init(document.getElementById('chart6'))
const option = {
textStyle: {
color: function() {
return 'rgb(' + [
Math.round(Math.random() * 160),
Math.round(Math.random() * 160),
Math.round(Math.random() * 160)
].join(',') + ')'
}
},
series: [{
type: 'wordCloud',
data: myData
}]
}
myChart.setOption(option)
myCharts.push(myChart)
}
</script>
<style scoped lang="scss">
.card{
background: #FFFFFF;
border-radius: 10px;
}
.dataItem{display: flex;align-items: center;margin:20px 5%;
border-right: 1px solid #eee;
&:last-child{border-right: none;}
img{width: 55px;height: 55px;margin-right: 8%;}
p{font-size: 15px;color: #7B7F83;margin:0 0 10px;}
h2{color: #2B3133;font-size: 1.8vw;margin: 0}
}
.home {
background: RGBA(245, 247, 249, 1);
font-family: "open sans", "Helvetica Neue", Helvetica, Arial, sans-serif;
font-size: 13px;
color: #676a6c;
overflow-x: hidden;
ul {
padding: 0;
margin: 0;list-style-type: none;
}
}
.homeTitle{font-weight: 500;color: #2B3133;margin: 30px 0 15px;}
.fiveflex{display: flex;justify-content: space-between;
.fitem{width: 18%;border-radius: 3px;display: flex;align-items: center; padding: 16px 15px;
p{color: #fff;}
img{margin-right: 20%;}
}
.wcard{width: 18%;border-radius: 10px;}
.ctitle{border-left:2px solid #20C59D;line-height: 1;padding-left: 10px;color: #2B3133;}
.cbody{display: flex;
p{width: 50%;
color: #7B7F83;}
span{display: block;
color: #2B3133;
font-size: 26px;}
}
.wfitem{display: flex; align-items: center;
img{margin-right: 20px; width: 55px;height: 55px;}
p{color: #7B7F83;}
span{display: block;font-size: 26px;color: #2B3133;}
}
}
.fitem:nth-child(1){background: linear-gradient(270deg, #54E1B9, #00CAA6);}
.fitem:nth-child(2){background: linear-gradient(270deg, #BE8EFB, #A76DF4);}
.fitem:nth-child(3){background: linear-gradient(90deg, #FEA449, #FFB95F);}
.fitem:nth-child(4){background: linear-gradient(270deg, #5E9AF3, #4169EC);}
.fitem:nth-child(5){background: linear-gradient(90deg, #F83841, #F76D74);}
.wcard{background: #fff; padding:15px;overflow: hidden;position: relative;
.po-title{position: absolute;
h3{font-size: 18px;color: #2B3133;margin: 0;}
h2{color: #014A9F;font-size: 30px;margin: 6px 0;}
p{color: #7B7F83;font-size: 18px;margin: 0;}
}
}
.quickbtns{
a{display: block;text-align: center;
background: #E5EDF5;
height: 70px;line-height: 70px;text-overflow: ellipsis;
overflow: hidden;white-space: nowrap;
font-size: 20px;margin-bottom: 20px;
color: #014A9F;
border-radius: 10px;
&:hover{color: #FFFFFF;background: #014A9F;}
}
}
.mesUl{
height: 270px; overflow: auto;
li{ position: relative;line-height: 45px;padding-left: 40px;
font-size: 16px;text-overflow: ellipsis;overflow: hidden;white-space: nowrap;
color: #666;cursor: pointer;
&:before{width: 6px;content: '';
height: 6px;position: absolute;left: 20px;top: 0;bottom: 0;margin: auto;
background: var(--el-color-primary);
border-radius: 50%;}
&:hover{background: #f4f4f4;}
.link{display: inline-block;}
}
}
.topflex{display: flex;justify-content: space-between;}
.mb40{margin-bottom: 40px;}
@media (max-width: 1400px) {
.quickbtns{
a{ font-size: 18px;}
}
.dataItem{
p { font-size: 14px;}
}
}
@media (max-width: 1200px) {
.quickbtns{
a{ font-size: 16px;}
}
}
</style>
<template>
<div class="app-container">
<div class="box">
<el-row :gutter="20">
<el-col :lg="5" :md="5" :xl="6" :sm="8" :xs="8">
<el-card class="mb20">
<div :class="language==0?'center-menu':'center-menu en-menu'">
<ul v-if="user.utype=='2'&&language==0">
<li v-for="(m, i) in menus"
:key="i"
:class="{ active: m.isActive }"
>
<a href="javascript:void(0)" @click="toInfo(m,menus)">
<img :src="m.isActive ? m.picUrl2 : m.picUrl1">
{{m.name }}
</a>
</li>
</ul>
<ul v-if="user.utype=='2'&&language==1">
<li v-for="(m, i) in menusEn"
:key="i"
:class="{ active: m.isActive }"
>
<a href="javascript:void(0)" @click="toInfo(m,menusEn)">
<img :src="m.isActive ? m.picUrl2 : m.picUrl1">
{{m.name }}
</a>
</li>
</ul>
<ul v-if="user.utype=='1'&&language==0">
<li
v-for="(m, i) in menusPersonal"
:key="i"
:class="{ active: m.isActive }"
>
<a href="javascript:void(0)" @click="toInfo(m,menusPersonal)">
<img :src="m.isActive ? m.picUrl2 : m.picUrl1">
{{ m.name }}
</a>
</li>
</ul>
<ul v-if="user.utype=='1'&&language==1">
<li
v-for="(m, i) in menusPersonalEn"
:key="i"
:class="{ active: m.isActive }"
>
<a href="javascript:void(0)" @click="toInfo(m,menusPersonalEn)">
<img :src="m.isActive ? m.picUrl2 : m.picUrl1">
{{ m.name }}
</a>
</li>
</ul>
<ul v-if="user.utype=='3'&&language==0">
<li
v-for="(m, i) in menus3"
:key="i"
:class="{ active: m.isActive }"
>
<a href="javascript:void(0)" @click="toInfo(m,menus3)">
<img :src="m.isActive ? m.picUrl2 : m.picUrl1">
{{ m.name }}
</a>
</li>
</ul>
<ul v-if="user.utype=='3'&&language==1">
<li
v-for="(m, i) in menus3En"
:key="i"
:class="{ active: m.isActive }"
>
<a href="javascript:void(0)" @click="toInfo(m,menus3En)">
<img :src="m.isActive ? m.picUrl2 : m.picUrl1">
{{ m.name }}
</a>
</li>
</ul>
</div>
</el-card>
</el-col>
<el-col :lg="19" :md="19" :xl="18" :sm="16" :xs="16">
<router-view :user="user" class="rightPart"/>
</el-col>
</el-row>
</div>
</div>
</template>
<script setup>
import {ref} from 'vue'
import {useRoute, useRouter} from 'vue-router'
import {onMounted} from '@vue/runtime-core'
import useUserStore from '@/store/modules/user'
import _ from 'lodash'
import {useStorage} from "@vueuse/core/index";
const language= useStorage('language',0)
const route = useRoute()
const router = useRouter()
const user = useUserStore().user || {}
const menus = ref([
{
name: language.value==0?'基础信息':'Basic Information',
routeName: 'myInfo',
picUrl1: '/img/nav_26.png',
picUrl2: '/img/nav_26_dwn.png',
isActive: false
},
{
name: language.value==0?'修改密码':'Change Password',
routeName: 'myPassword',
picUrl1: '/img/nav_27.png',
picUrl2: '/img/nav_27_dwn.png',
isActive: false
},
{
name: language.value==0?'团队认证':'Organization Recognition',
routeName: 'myCertification',
picUrl1: '/img/nav_32.png',
picUrl2: '/img/nav_32_dwn.png',
isActive: false
},
{
name: language.value==0?'选手管理':'Athlete Management',
routeName: 'myMember',
picUrl1: '/img/nav_31.png',
picUrl2: '/img/nav_31_dwn.png',
isActive: false
},
{
name: language.value==0?'我的报名':'My Registration',
routeName: 'myMatch',
picUrl1: '/img/nav_28.png',
picUrl2: '/img/nav_28_dwn.png',
isActive: false
},
{
name: language.value==0?'我的预订':'My Reservation',
routeName: 'myReservation',
picUrl1: '/img/nav_29.png',
picUrl2: '/img/nav_29_dwn.png',
isActive: false
},
{
name: language.value==0?'票务预订':'Ticket Reservation',
routeName: 'seat_order',
picUrl1: '/img/c7.png',
picUrl2: '/img/c7.png',
isActive: false
},
{
name: language.value==0?'系统消息':'System messages',
routeName: 'mySms',
picUrl1: '/img/nav_30.png',
picUrl2: '/img/nav_30_dwn.png',
isActive: false
},
{
name: language.value==0?'发票申请':'Electronic invoice',
routeName: 'myKP',
picUrl1: '/img/fp.svg',
picUrl2: '/img/fp_dwn.svg',
isActive: false
}
])
const menusEn = ref([
{
name: language.value==0?'基础信息':'Basic Information',
routeName: 'myInfo',
picUrl1: '/img/nav_26.png',
picUrl2: '/img/nav_26_dwn.png',
isActive: false
},
{
name: language.value==0?'修改密码':'Change Password',
routeName: 'myPassword',
picUrl1: '/img/nav_27.png',
picUrl2: '/img/nav_27_dwn.png',
isActive: false
},
{
name: language.value==0?'团队认证':'Organization Recognition',
routeName: 'myCertification',
picUrl1: '/img/nav_32.png',
picUrl2: '/img/nav_32_dwn.png',
isActive: false
},
{
name: language.value==0?'选手管理':'Athlete Management',
routeName: 'myMember',
picUrl1: '/img/nav_31.png',
picUrl2: '/img/nav_31_dwn.png',
isActive: false
},
{
name: language.value==0?'我的报名':'My Registration',
routeName: 'myMatch',
picUrl1: '/img/nav_28.png',
picUrl2: '/img/nav_28_dwn.png',
isActive: false
},
{
name: language.value==0?'我的预订':'My Reservation',
routeName: 'myReservation',
picUrl1: '/img/nav_29.png',
picUrl2: '/img/nav_29_dwn.png',
isActive: false
},
{
name: language.value==0?'票务预订':'Ticket Reservation',
routeName: 'seat_order',
picUrl1: '/img/c7.png',
picUrl2: '/img/c7.png',
isActive: false
},
{
name: language.value==0?'系统消息':'System messages',
routeName: 'mySms',
picUrl1: '/img/nav_30.png',
picUrl2: '/img/nav_30_dwn.png',
isActive: false
}
])
const menus3 = ref([
{
name: language.value==0?'基础信息':'Basic Information',
routeName: 'myInfo',
picUrl1: '/img/nav_26.png',
picUrl2: '/img/nav_26_dwn.png',
isActive: false
},
{
name: language.value==0?'修改密码':'Change Password',
routeName: 'myPassword',
picUrl1: '/img/nav_27.png',
picUrl2: '/img/nav_27_dwn.png',
isActive: false
},
{
name: language.value==0?'我的预订':'My Reservation',
routeName: 'myReservation',
picUrl1: '/img/nav_29.png',
picUrl2: '/img/nav_29_dwn.png',
isActive: false
},
{
name: language.value==0?'票务预订':'Ticket Reservation',
routeName: 'seat_order',
picUrl1: '/img/c7.png',
picUrl2: '/img/c7.png',
isActive: false
},
{
name: language.value==0?'发票申请':'Electronic invoice',
routeName: 'myKP',
picUrl1: '/img/fp.svg',
picUrl2: '/img/fp_dwn.svg',
isActive: false
}
])
const menus3En = ref([
{
name: language.value==0?'基础信息':'Basic Information',
routeName: 'myInfo',
picUrl1: '/img/nav_26.png',
picUrl2: '/img/nav_26_dwn.png',
isActive: false
},
{
name: language.value==0?'修改密码':'Change Password',
routeName: 'myPassword',
picUrl1: '/img/nav_27.png',
picUrl2: '/img/nav_27_dwn.png',
isActive: false
},
{
name: language.value==0?'我的预订':'My Reservation',
routeName: 'myReservation',
picUrl1: '/img/nav_29.png',
picUrl2: '/img/nav_29_dwn.png',
isActive: false
},
{
name: language.value==0?'票务预订':'Ticket Reservation',
routeName: 'seat_order',
picUrl1: '/img/c7.png',
picUrl2: '/img/c7.png',
isActive: false
}
])
const menusPersonal = ref([
{
name: language.value==0?'基础信息':'Basic Information',
routeName: 'myInfo',
picUrl1: '/img/nav_26.png',
picUrl2: '/img/nav_26_dwn.png',
isActive: false
},
{
name: language.value==0?'修改密码':'Change Password',
routeName: 'myPassword',
picUrl1: '/img/nav_27.png',
picUrl2: '/img/nav_27_dwn.png',
isActive: false
},
{
name: language.value==0?'我的报名':'My Registration',
routeName: 'myMatch',
picUrl1: '/img/nav_28.png',
picUrl2: '/img/nav_28_dwn.png',
isActive: false
},
{
name: language.value==0?'我的预订':'My Reservation',
routeName: 'myReservation',
picUrl1: '/img/nav_29.png',
picUrl2: '/img/nav_29_dwn.png',
isActive: false
},
{
name: language.value==0?'票务预订':'Ticket Reservation',
routeName: 'seat_order',
picUrl1: '/img/c7.png',
picUrl2: '/img/c7.png',
isActive: false
},
{
name: language.value==0?'系统消息':'System messages',
routeName: 'mySms',
picUrl1: '/img/nav_30.png',
picUrl2: '/img/nav_30_dwn.png',
isActive: false
},
{
name: language.value==0?'发票申请':'Electronic invoice',
routeName: 'myKP',
picUrl1: '/img/fp.svg',
picUrl2: '/img/fp_dwn.svg',
isActive: false
}
])
const menusPersonalEn = ref([
{
name: language.value==0?'基础信息':'Basic Information',
routeName: 'myInfo',
picUrl1: '/img/nav_26.png',
picUrl2: '/img/nav_26_dwn.png',
isActive: false
},
{
name: language.value==0?'修改密码':'Change Password',
routeName: 'myPassword',
picUrl1: '/img/nav_27.png',
picUrl2: '/img/nav_27_dwn.png',
isActive: false
},
{
name: language.value==0?'我的报名':'My Registration',
routeName: 'myMatch',
picUrl1: '/img/nav_28.png',
picUrl2: '/img/nav_28_dwn.png',
isActive: false
},
{
name: language.value==0?'我的预订':'My Reservation',
routeName: 'myReservation',
picUrl1: '/img/nav_29.png',
picUrl2: '/img/nav_29_dwn.png',
isActive: false
},
{
name: language.value==0?'票务预订':'Ticket Reservation',
routeName: 'seat_order',
picUrl1: '/img/c7.png',
picUrl2: '/img/c7.png',
isActive: false
},
{
name: language.value==0?'系统消息':'System messages',
routeName: 'mySms',
picUrl1: '/img/nav_30.png',
picUrl2: '/img/nav_30_dwn.png',
isActive: false
}
])
let currMenu
onMounted(() => {
console.log(route.query)
if(!user.utype){
router.push({name: 'home'})
return
}
if(user.utype=='1'){
currMenu = _.find(menusPersonal.value, (m) => {
return m.routeName === route.name
})
currMenu.isActive = true
}
console.log(route.name)
if(user.utype=='2'){
currMenu = _.find(menus.value, (m) => {
return m.routeName === route.name
})
currMenu.isActive = true
}
if(user.utype=='3'){
currMenu = _.find(menus3.value, (m) => {
return m.routeName === route.name
})
currMenu.isActive = true
}
})
const toInfo = (item,list) => {
_.each(list, (m) => {
m.isActive = false
})
item.isActive = true
router.push({
name: item.routeName
})
}
</script>
<style scoped lang="scss">
:deep(.el-tabs__nav-wrap) {
padding: 0 15px;
}
.center-menu {
text-align: center;
li {
margin-bottom: 15px;
}
&.en-menu{text-align: left;
li{padding: 6px 0 6px 14px;
a{display: flex;align-items: center;}
}
img{padding: 0;width: 26px;}
}
}
li img {
display: inline-block;
vertical-align: middle;
margin-right: 10px;
padding: 5px;
}
.active {
color: #fff;
background: linear-gradient(90deg, #8623FC, #453DEA);
border-radius: 20px;
}
@media (max-width: 500px) {
.pd20{padding: 8px;}
.el-card{box-shadow: none!important;
:deep(.el-card__body){padding: 0!important;}
}
.el-col{padding: 0!important;}
.center-menu{height: 100vh;padding: 20px 0;position: fixed;left: 0;z-index: 1;
background: #F5F7F9;top: 80px;width: 100px;border-right: 1px solid #eee;
li{font-size: 13px;padding:8px 10px;border-radius: 0;
img{display: none}
&.active{background: #fff;
border-left: 2px solid var(--el-color-primary);
color: var(--el-color-primary);}
}
}
.rightPart{width: calc(100vw - 100px);left: 100px;position: fixed; z-index: 1;
height: calc(100vh - 80px);overflow: auto;top: 80px;background: #fff;
}
}
.app-container{min-height: 80vh;}
</style>
<template>
<div class="mb20">
<el-card :body-style="{'padding':'0'}">
<div class="indexTitle">
<h3 class="leftboderTT" v-if="user.utype=='2'">
{{ language == 0 ? '机构基础信息' : 'ORGANIZATION BASIC INFORMATION' }}</h3>
<h3 class="leftboderTT" v-if="user.utype=='1'">{{
language == 0 ? '个人基础信息' : 'Personal Basic Information'
}}</h3>
</div>
<!-- uType字段 1 是个人 2是团体-->
<!-- {{user}}-->
<team-info :form="myform" v-if="user.utype=='2'"/>
<div class="pd20" v-else>
<div class="d-form-border" style="margin-top: 0">
<el-form class="d-form" label-width="120" :rules="rules" ref="formref"
:label-position="language==0?'left':'top'" style="max-width: 500px;margin: auto">
<el-form-item :label="language==0?'用户名':'Account'">
{{ user.userName }}
</el-form-item>
<el-form-item :label="language==0?'姓名':'Real Name'" required prop="realName" v-if="user.utype=='1'">
<el-input v-model="myform.realName" disabled/>
</el-form-item>
<el-form-item :label="language==0?'性别':'Gender'" required >
<el-radio-group v-model="myform.sex">
<el-radio value="0">{{ language == 0 ? '女' : 'female' }}</el-radio>
<el-radio value="1">{{ language == 0 ? '男' : 'male' }}</el-radio>
</el-radio-group>
</el-form-item>
<el-form-item :label="language==0?'出生日期':'Date of Birth'">
<el-date-picker
v-model="myform.birth"
style="width: 100%;"
type="date" format="YYYY-MM-DD" value-format="YYYY-MM-DD"
/>
</el-form-item>
<el-form-item :label="language==0?'代表':'Representing'" required v-if="user.utype=='1'">
<el-input v-model="myform.representing" disabled/>
</el-form-item>
<el-form-item :label="language==1?'Age group':'年龄组'" required v-if="user.utype=='1'">
<el-input v-model="myform.ageGroup" disabled/>
</el-form-item>
<el-form-item :label="language==0?'舞种':'Division'" required v-if="user.utype=='1'">
<el-input v-model="myform.division" disabled/>
</el-form-item>
<el-form-item :label="language==0?'状态':'Status'" required v-if="user.utype=='1'">
<el-input v-model="myform.wdsfStatus" disabled/>
</el-form-item>
<el-form-item :label="language==0?'证件号':'Passport number'" required v-if="user.utype=='1'">
<el-input v-model="myform.passportNumber" disabled/>
</el-form-item>
<el-form-item :label="language==0?'有效证件':'Valid Passport'" required v-if="user.utype=='1'">
<image-upload v-model="myform.passportUrl" :limit="1" :is-show-tip="false"
:button-text="language==0?'上传':'Upload'"/>
</el-form-item>
<el-form-item :label="language==0?'WDSF会员号':'WDSF MIN'" prop="wdsfMin" v-if="user.utype=='1'">
{{myform.wdsfMin}}
</el-form-item>
<!-- <el-form-item :label="language==0?'证件类型':'ID type'" required prop="idcType">-->
<!-- <el-select v-model="myform.idcType" style="width: 100%">-->
<!-- <el-option-->
<!-- v-for="item in certificates"-->
<!-- :key="item.value"-->
<!-- :label="item.label"-->
<!-- :value="item.value"-->
<!-- />-->
<!-- </el-select>-->
<!-- </el-form-item>-->
<!-- <el-form-item :label="language==0?'证件号码':'ID NO'" prop="idcCode">-->
<!-- <el-input v-model="myform.idcCode" @blur="checkCode"/>-->
<!-- </el-form-item>-->
<!-- <el-form-item :label="language==0?'类型':'Type'" required>-->
<!-- <el-select v-model="myform.type" style="width: 100%;">-->
<!-- <el-option :label="language==0?'业余':'amateur'" value="0"/>-->
<!-- <el-option :label="language==0?'专业':'Professional'" value="1"/>-->
<!-- <el-option :label="language==0?'大专院校':'Colleges and universities'" value="2"/>-->
<!-- <el-option :label="language==0?'其他':'Other'" value="3"/>-->
<!-- </el-select>-->
<!-- </el-form-item>-->
<!-- <el-form-item :label="language==0?'邮箱':'Email'" required prop="email">-->
<!-- <el-input v-model="myform.email" type="email" :placeholder="language==0?'请输入内容':''"/>-->
<!-- </el-form-item>-->
</el-form>
<div class="text-center" v-if="user.utype=='1'||user.utype=='2'">
<el-button type="primary" class="btn-lineG" round @click="save">
{{language == 0 ? '确定修改' : 'Save'}}
</el-button>
</div>
</div>
</div>
</el-card>
</div>
</template>
<script setup>
import {ref} from 'vue'
import {useRouter} from 'vue-router'
import {getCurrentInstance, onMounted} from '@vue/runtime-core'
import * as match from '@/apiPc/match'
import {ElMessage, ElMessageBox} from 'element-plus'
import useUserStore from "@/store/modules/user";
import {useStorage} from "@vueuse/core/index";
const language= useStorage('language',0)
const router = useRouter()
const {proxy} = getCurrentInstance()
const props = defineProps({
user: {
type: Object,
required: true
}
})
const rules = ref({
realName: [{required: true, message: '必填', trigger: 'blur'}],
sex: [{required: true, message: '必填', trigger: 'change'}],
idcType: [{required: true, message: '必填', trigger: 'change'}],
type: [{required: true, message: '必填', trigger: 'change'}],
idcCode: [{required: true, message: '必填', trigger: 'blur'}],
email: [{required: true, message: '必填', trigger: 'blur'}],
})
const activeName = ref('first')
const myform = ref({
idcType: 0,
countryId: '',
realName: ''
})
const labelArr = ref([])
const certificates = ref([
{
value: '0',
label: language.value == 0 ? '居民身份证' : 'Resident ID card'
},
{
value: '1',
label: language.value == 0 ? '护照' : 'Passport'
},
{
value: '2',
label: language.value == 0 ? '其他' : 'Other'
}
])
const user = useUserStore().user || {}
getData()
function getData() {
if (user.utype == '2') {
match.getGroupInfo().then(res => {
myform.value = res.data
})
}
if (user.utype == '1') {
match.getMyPersonInfo().then(res => {
myform.value = res.data
if(language.value=='1'){
myform.value.type = '1'
}
})
}
}
function save() {
match.saveMyBaseInfo(myform.value).then(res => {
ElMessage.success(language.value==0?'保存成功':'Save successfully')
})
}
function checkCode() {
if (myform.value.idcType == 0 && myform.value.idcCode) {
if (!(/(^\d{15}$)|(^\d{17}([0-9]|X)$)/.test(myform.value.idcCode))) {
ElMessage.warning('请输入正确的身份证号码')
} else {
let tmpStr = ''
if (myform.value.idcCode.length == 15) {
tmpStr = myform.value.idcCode.substring(6, 12)
tmpStr = '19' + tmpStr
tmpStr = tmpStr.substring(0, 4) + '-' + tmpStr.substring(4, 6) + '-' + tmpStr.substring(6)
} else {
tmpStr = myform.value.idcCode.substring(6, 14)
tmpStr = tmpStr.substring(0, 4) + '-' + tmpStr.substring(4, 6) + '-' + tmpStr.substring(6)
}
myform.value.birth = tmpStr
const res = /^(\d{6})(\d{4})(\d{2})(\d{2})(\d{3})([0-9]|X)$/
if (myform.value.idcCode && res.test(myform.value.idcCode)) {
const genderCode = myform.value.idcCode.charAt(16)
if (parseInt(genderCode) % 2 == 0) {
myform.value.sex = '0'
} else {
myform.value.sex = '1'
}
}
}
}
}
</script>
<style scoped lang="scss">
.indexTitle {
margin: 20px 0 12px;
padding: 0 20px 15px;
border-bottom: 1px solid #e5e5e5;
h3 {
font-size: 16px;
color: var(--el-color-primary);
}
}
</style>
<template>
<div class="mb20">
<el-card :body-style="{'padding':'0'}">
<div class="indexTitle"><h3 class="leftboderTT">{{ language==0?'修改密码':'Change Password' }}</h3></div>
<div class="pd20">
<div class="d-form-border" style="margin-top: 0">
<el-form class="d-form" ref="pwdRef" :model="user" :rules="rules"
label-width="120px" :label-position="language==0?'left':'top'"
style="max-width: 500px;margin: auto">
<el-form-item :label="language==0?'旧密码':'Old Password'" prop="oldPassword">
<el-input v-model="user.oldPassword" :placeholder="language==0?'请输入旧密码':''" type="password" show-password/>
</el-form-item>
<el-form-item :label="language==0?'新密码':'New Password'" prop="newPassword">
<el-input v-model="user.newPassword" :placeholder="language==0?'请设置8位以上大小写字母、数字、特殊符号':''" type="password"
show-password/>
</el-form-item>
<el-form-item :label="language==0?'确认密码':'Confirm Password'" prop="confirmPassword">
<el-input v-model="user.confirmPassword" :placeholder="language==0?'请确认新密码':''" type="password" show-password/>
</el-form-item>
</el-form>
</div>
<el-row justify="center">
<el-button type="primary" class="btn-lineG" round @click="submit">{{ language==0?'保存':'Save' }}</el-button>
</el-row>
</div>
</el-card>
</div>
</template>
<script setup>
import {updateUserPwd} from '@/api/system/user'
import useUserStore from '@/store/modules/user'
import {reactive, ref, getCurrentInstance} from 'vue'
import {validPassword} from '@/utils/validate'
import {useStorage} from "@vueuse/core/index";
const language = useStorage('language', 0)
const show = ref(false)
const {proxy} = getCurrentInstance()
const userStore = useUserStore()
const user = reactive({
oldPassword: undefined,
newPassword: undefined,
confirmPassword: undefined
})
const equalToPassword = (rule, value, callback) => {
if (user.newPassword !== value) {
callback(new Error('两次输入的密码不一致'))
} else {
callback()
}
}
const validPwd = (rule, value, callback) => {
if (import.meta.env.DEV) {
callback()
} else {
if (!validPassword(value)) {
callback(new Error('请设置8位以上大小写字母、数字、特殊符号组合的密码'))
} else {
callback()
}
}
}
const rules = ref({
oldPassword: [{required: true, message: language.value==0?'旧密码不能为空':'required', trigger: 'blur'}],
newPassword: [
{required: true, message: language.value==0?'新密码不能为空':'required', trigger: 'blur'},
{validator: validPwd, trigger: 'blur'}
],
confirmPassword: [
{required: true, message: language.value==0?'确认密码不能为空':'required', trigger: 'blur'},
{required: true, validator: equalToPassword, trigger: 'blur'}
]
})
/** 提交按钮 */
function submit() {
proxy.$refs['pwdRef'].validate(valid => {
if (valid) {
updateUserPwd(user.oldPassword, user.newPassword).then(response => {
proxy.$modal.msgSuccess(language.value==0?'修改成功':'password is changed!')
userStore.logOut().then(() => {
setTimeout(() => {
location.reload()
}, 1000)
})
})
}
})
}
</script>
<style scoped lang="scss">
.indexTitle {
margin: 20px 0 12px;
padding: 0 20px 15px;
border-bottom: 1px solid #e5e5e5;
h3 {
font-size: 16px;
color: var(--el-color-primary);
}
}
</style>
......@@ -2,8 +2,6 @@
<!-- -->
<div class="partA">
<rotate-part>
</rotate-part>
<div class="gif_bg">
<img src="@/assets/img/rote.png">
......@@ -93,7 +91,6 @@
</template>
<script setup>
import rotatePart from './rotatePart'
import {onMounted, ref, watch} from 'vue'
import {ArrowRight} from '@element-plus/icons-vue'
import {szToHz} from '@/utils/ruoyi'
......
<template>
<div class="ellipse">
<div :class="`circle circle${i+1}`" v-for="(n,i) in list">
<div class="ma">
<!-- <img v-if="i >= 0 && i < 5" :class="`iconImg`" :src="getBtnImagePath(i)">-->
<img v-if="i==0" class="iconImg" src="@/assets/img/btn01.png">
<img v-if="i==1" class="iconImg" src="@/assets/img/btn02.png">
<img v-if="i==2" class="iconImg" src="@/assets/img/btn03.png">
<img v-if="i==3" class="iconImg" src="@/assets/img/btn04.png">
<img v-if="i==4" class="iconImg" src="@/assets/img/btn05.png">
<div class="statistic">
<h3>{{n.name}}</h3>
<p v-if="Array.isArray(n.num)">
{{Number(n.num[0]/10000).toFixed(2)}} 万卷/<br/>
{{Number(n.num[1]/10000).toFixed(2)}} 万件
</p>
<p v-else>{{n.num}}</p>
</div>
<!-- <el-statistic class="statistic" :title="n.name" :value="Array.isArray(n.num)?`${n.num[0]}卷/${n.num[1]}件`:n.num" :value-style="statisticStyle"></el-statistic>-->
</div>
</div>
</div>
</template>
<script setup>
import {onMounted, ref} from "vue";
import {Swiper, SwiperSlide} from 'swiper/vue'
import {Autoplay, Navigation} from 'swiper'
import * as api from "@/apiPc/common"
const statisticStyle = ref({'color':'#fff'})
const modules = ref([Autoplay])
const list =ref([])
let intervalA = null
onMounted(()=>{
init()
})
function init() {
if(!intervalA){
getdata()
}
intervalA = setInterval(getdata, 1000*60*60);
}
const getdata = () => {
api.getBasicInfo().then(res=>{
list.value = []
let arr = res.data
for (let n in arr){
let obj = {name:n,num:arr[n]}
list.value.push(obj)
}
})
}
function getBtnImagePath(index) {
return require(`@/assets/img/btn${index + 1}.png`);
}
//动画的暂停与开始
var svg1 = document.getElementById("svg_an");
function pauseAn() {
svg1.pauseAnimations();
}
function unpauseAn() {
svg1.unpauseAnimations();
}
</script>
<style scoped lang="scss">
/* 定义旋转动画 */
@keyframes rotate {
0%{
transform: rotate3d(1,1,1,0deg);
}
100%{
transform: rotate3d(1,1,1,360deg);
}
}
:deep(.el-statistic__head){
font-family: 'YouSheBiaoTiHei';
background: linear-gradient(180deg, #fff 10%, #9CD2FF 100%);
-webkit-background-clip: text;
-webkit-text-fill-color: transparent;
font-size: calc(20*100vw/1920);
line-height: 1.6;
}
:deep(.el-statistic__number){
font-size: calc(26*100vw/1920);
font-family: 'DIN Alternate';
background: linear-gradient(180deg, #fff 20%, #9CD2FF 100%);
-webkit-background-clip: text;
-webkit-text-fill-color: transparent;
}
.statistic{--el-statistic-title-color: #fff;text-align: center;position: relative;
top: calc(-20*100vw/1920);
h3{color: #fff; font-family: 'YouSheBiaoTiHei';
background: linear-gradient(180deg, #fff 10%, #9CD2FF 100%);
-webkit-background-clip: text;
-webkit-text-fill-color: transparent;
font-size: calc(22*100vw/1920);
line-height: 1;margin: 0}
p{color: #fff; background: linear-gradient(180deg, #fff 20%, #9CD2FF 100%);
-webkit-background-clip: text; font-size: calc(26*100vw/1920);
font-family: 'DIN Alternate';
-webkit-text-fill-color: transparent;line-height: 1;overflow: visible;
margin: 0;height: calc(60*100vw/1920);display: flex;align-items: center;justify-content: center;
span{font-size: calc(22*100vw/1920);}
}
}
.ellipse {
position: relative;
left: -3%;
width: 100%;margin: auto;
height: 100%;
border-radius: 50%;z-index: 10;
//border: 2px #fff solid;
transform-style: preserve-3d;
transform: rotateZ(90deg) rotateY(60deg);
&:hover .circle{ animation-play-state: paused!important;}
}
.ellipse .circle {
width: calc(300*100vw/1920);
height: calc(400*100vw/1920);
top: 0;
left: 0;
right: 0;
bottom: 0;
margin: auto;
position: absolute;
text-align: center;opacity: 1;filter: brightness(100%);
&:hover{
animation-play-state: paused;
}
}
.ellipse .circle .ma{
background: url("@/assets/img/mabg.png") no-repeat center;
background-size: contain;
//box-shadow: 0 0 20px #000;
display: block;
height: calc(340*100vw/1920); width:calc(290*100vw/1920);
transform: rotateZ(-90deg); /* 再次旋转 */
img{width: 70%;position: relative;top:0;margin: 0 auto calc(60*100vw/1920);}
}
.ellipse .circle1{
animation: moveA 30s linear infinite;
}
.ellipse .circle2{
animation: moveB 30s linear infinite;
}
.ellipse .circle3{
animation: moveC 30s linear infinite;
}
.ellipse .circle4{
animation: moveD 30s linear infinite;
}
.ellipse .circle5{
animation: moveE 30s linear infinite;
}
@keyframes moveA {
0% {
transform: rotateZ(0) translateX(calc(300*100vw/1920)) rotateZ(0) rotateY(-70deg) scale(1);
filter: brightness(100%);
}
5% {
transform: rotateZ(80deg) translateX(calc(300*100vw/1920)) rotateZ(-80deg) rotateY(-70deg) scale(0.8);
filter: brightness(80%);
}
20% {
transform: rotateZ(80deg) translateX(calc(300*100vw/1920)) rotateZ(-80deg) rotateY(-70deg) scale(0.8);
filter: brightness(80%);
}
25% {
transform: rotateZ(160deg) translateX(calc(300*100vw/1920)) rotateZ(-160deg) rotateY(-70deg) scale(0.7);
filter: brightness(60%);
}
40% {
transform: rotateZ(160deg) translateX(calc(300*100vw/1920)) rotateZ(-160deg) rotateY(-70deg) scale(0.7);
filter: brightness(60%);
}
45% {
transform: rotateZ(200deg) translateX(calc(300*100vw/1920)) rotateZ(-200deg) rotateY(-70deg) scale(0.7);
filter: brightness(60%);
}
60% {
transform: rotateZ(200deg) translateX(calc(300*100vw/1920)) rotateZ(-200deg) rotateY(-70deg) scale(0.7);
filter: brightness(60%);
}
65% {
transform: rotateZ(280deg) translateX(calc(300*100vw/1920)) rotateZ(-280deg) rotateY(-70deg) scale(0.8);
filter: brightness(80%);
}
80% {
transform: rotateZ(280deg) translateX(calc(300*100vw/1920)) rotateZ(-280deg) rotateY(-70deg) scale(0.8);
filter: brightness(80%);
}
85% {
transform: rotateZ(360deg) translateX(calc(300*100vw/1920)) rotateZ(-360deg) rotateY(-70deg) scale(1);
filter: brightness(100%);
}
100% {
transform: rotateZ(360deg) translateX(calc(300*100vw/1920)) rotateZ(-360deg) rotateY(-70deg) scale(1);
filter: brightness(100%);
}
}
@keyframes moveB {
0% {
transform: rotateZ(-80deg) translateX(calc(300*100vw/1920)) rotateZ(80deg) rotateY(-70deg) scale(0.8);
filter: brightness(80%);
}
5% {
transform: rotateZ(0deg) translateX(calc(300*100vw/1920)) rotateZ(0deg) rotateY(-70deg) scale(1);
z-index: 99;filter: brightness(100%);
}
20% {
transform: rotateZ(0deg) translateX(calc(300*100vw/1920)) rotateZ(0deg) rotateY(-70deg) scale(1);
z-index: 99;filter: brightness(100%);
}
25% {
transform: rotateZ(80deg) translateX(calc(300*100vw/1920)) rotateZ(-80deg) rotateY(-70deg) scale(0.8);
filter: brightness(80%);
}
40% {
transform: rotateZ(80deg) translateX(calc(300*100vw/1920)) rotateZ(-80deg) rotateY(-70deg) scale(0.8);
filter: brightness(80%);
}
45% {
transform: rotateZ(160deg) translateX(calc(300*100vw/1920)) rotateZ(-160deg) rotateY(-70deg) scale(0.7);
filter: brightness(60%);
}
60% {
transform: rotateZ(160deg) translateX(calc(300*100vw/1920)) rotateZ(-160deg) rotateY(-70deg) scale(0.7);
filter: brightness(60%);
}
65% {
transform: rotateZ(200deg) translateX(calc(300*100vw/1920)) rotateZ(-200deg) rotateY(-70deg) scale(0.7);
filter: brightness(60%);
}
80% {
transform: rotateZ(200deg) translateX(calc(300*100vw/1920)) rotateZ(-200deg) rotateY(-70deg) scale(0.7);
filter: brightness(60%);
}
85% {
transform: rotateZ(280deg) translateX(calc(300*100vw/1920)) rotateZ(-280deg) rotateY(-70deg) scale(0.8);
filter: brightness(80%);
}
100% {
transform: rotateZ(280deg) translateX(calc(300*100vw/1920)) rotateZ(-280deg) rotateY(-70deg) scale(0.8);
filter: brightness(80%);
}
}
@keyframes moveC {
0% {
transform: rotateZ(-160deg) translateX(calc(300*100vw/1920)) rotateZ(160deg) rotateY(-70deg) scale(0.7);
filter: brightness(60%);
}
5% {
transform: rotateZ(-80deg) translateX(calc(300*100vw/1920)) rotateZ(80deg) rotateY(-70deg) scale(0.8);
filter: brightness(80%);
}
20% {
transform: rotateZ(-80deg) translateX(calc(300*100vw/1920)) rotateZ(80deg) rotateY(-70deg) scale(0.8);
filter: brightness(80%);
}
25% {
transform: rotateZ(0deg) translateX(calc(300*100vw/1920)) rotateZ(0deg) rotateY(-70deg) scale(1);
filter: brightness(100%);z-index: 99;
}
40% {
transform: rotateZ(0deg) translateX(calc(300*100vw/1920)) rotateZ(0deg) rotateY(-70deg) scale(1);
filter: brightness(100%);z-index: 99;
}
45% {
transform: rotateZ(80deg) translateX(calc(300*100vw/1920)) rotateZ(-80deg) rotateY(-70deg) scale(0.8);
filter: brightness(80%);
}
60% {
transform: rotateZ(80deg) translateX(calc(300*100vw/1920)) rotateZ(-80deg) rotateY(-70deg) scale(0.8);
filter: brightness(80%);
}
65% {
transform: rotateZ(160deg) translateX(calc(300*100vw/1920)) rotateZ(-160deg) rotateY(-70deg) scale(0.7);
filter: brightness(60%);
}
80% {
transform: rotateZ(160deg) translateX(calc(300*100vw/1920)) rotateZ(-160deg) rotateY(-70deg) scale(0.7);
filter: brightness(60%);
}
85% {
transform: rotateZ(200deg) translateX(calc(300*100vw/1920)) rotateZ(-200deg) rotateY(-70deg) scale(0.7);
filter: brightness(60%);
}
100% {
transform: rotateZ(200deg) translateX(calc(300*100vw/1920)) rotateZ(-200deg) rotateY(-70deg) scale(0.7);
filter: brightness(60%);
}
}
@keyframes moveD {
0% {
transform: rotateZ(-200deg) translateX(calc(300*100vw/1920)) rotateZ(200deg) rotateY(-70deg) scale(0.7);
filter: brightness(60%);
}
5% {
transform: rotateZ(-160deg) translateX(calc(300*100vw/1920)) rotateZ(160deg) rotateY(-70deg) scale(0.7);
filter: brightness(60%);
}
20% {
transform: rotateZ(-160deg) translateX(calc(300*100vw/1920)) rotateZ(160deg) rotateY(-70deg) scale(0.7);
filter: brightness(60%);
}
25% {
transform: rotateZ(-80deg) translateX(calc(300*100vw/1920)) rotateZ(80deg) rotateY(-70deg) scale(0.8);
filter: brightness(80%);
}
40% {
transform: rotateZ(-80deg) translateX(calc(300*100vw/1920)) rotateZ(80deg) rotateY(-70deg) scale(0.8);
filter: brightness(80%);
}
45% {
transform: rotateZ(0deg) translateX(calc(300*100vw/1920)) rotateZ(0deg) rotateY(-70deg) scale(1);
filter: brightness(100%);z-index: 99;
}
60% {
transform: rotateZ(0deg) translateX(calc(300*100vw/1920)) rotateZ(0deg) rotateY(-70deg) scale(1);
filter: brightness(100%);z-index: 99;
}
65% {
transform: rotateZ(80deg) translateX(calc(300*100vw/1920)) rotateZ(-80deg) rotateY(-70deg) scale(0.8);
filter: brightness(80%);
}
80% {
transform: rotateZ(80deg) translateX(calc(300*100vw/1920)) rotateZ(-80deg) rotateY(-70deg) scale(0.8);
filter: brightness(80%);
}
85% {
transform: rotateZ(160deg) translateX(calc(300*100vw/1920)) rotateZ(-160deg) rotateY(-70deg) scale(0.7);
filter: brightness(60%);
}
100% {
transform: rotateZ(160deg) translateX(calc(300*100vw/1920)) rotateZ(-160deg) rotateY(-70deg) scale(0.7);
filter: brightness(60%);
}
}
@keyframes moveE {
0% {
transform: rotateZ(-280deg) translateX(calc(300*100vw/1920)) rotateZ(280deg) rotateY(-70deg) scale(0.8);
filter: brightness(80%);
}
5% {
transform: rotateZ(-200deg) translateX(calc(300*100vw/1920)) rotateZ(200deg) rotateY(-70deg) scale(0.7);
filter: brightness(60%);
}
20% {
transform: rotateZ(-200deg) translateX(calc(300*100vw/1920)) rotateZ(200deg) rotateY(-70deg) scale(0.7);
filter: brightness(60%);
}
25% {
transform: rotateZ(-160deg) translateX(calc(300*100vw/1920)) rotateZ(160deg) rotateY(-70deg) scale(0.7);
filter: brightness(60%);
}
40% {
transform: rotateZ(-160deg) translateX(calc(300*100vw/1920)) rotateZ(160deg) rotateY(-70deg) scale(0.7);
filter: brightness(60%);
}
45% {
transform: rotateZ(-80deg) translateX(calc(300*100vw/1920)) rotateZ(80deg) rotateY(-70deg) scale(0.7);
filter: brightness(80%);
}
60% {
transform: rotateZ(-80deg) translateX(calc(300*100vw/1920)) rotateZ(80deg) rotateY(-70deg) scale(0.7);
filter: brightness(80%);
}
65% {
transform: rotateZ(0deg) translateX(calc(300*100vw/1920)) rotateZ(0deg) rotateY(-70deg) scale(1);
filter: brightness(100%);z-index: 99;
}
80% {
transform: rotateZ(0deg) translateX(calc(300*100vw/1920)) rotateZ(0deg) rotateY(-70deg) scale(1);
filter: brightness(100%);z-index: 99;
}
85% {
transform: rotateZ(80deg) translateX(calc(300*100vw/1920)) rotateZ(-80deg) rotateY(-70deg) scale(0.8);
filter: brightness(80%);
}
100% {
transform: rotateZ(80deg) translateX(calc(300*100vw/1920)) rotateZ(-80deg) rotateY(-70deg) scale(0.8);
filter: brightness(80%);
}
}
</style>
Styling with Markdown is supported
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!