63cea824 by 杨炀

init

1 parent dce034b2
1 <template>
2 <div class="app-container home">
3 <el-row class="card">
4 <el-col :span="6">
5 <div class="dataItem">
6 <div>
7 <p>个人会员</p>
8 <h2>{{ players }}</h2>
9 </div>
10 </div>
11 </el-col>
12 <el-col :span="6">
13 <div class="dataItem">
14 <div><p>团体会员</p>
15 <h2>{{ members }}</h2></div>
16 </div>
17 </el-col>
18 <el-col :span="6">
19 <div class="dataItem">
20 <div><p>即将到期会员</p>
21 <h2>{{ soonGuoqiPers }}</h2></div>
22 </div>
23 </el-col>
24 <el-col :span="6">
25 <div class="dataItem">
26 <div><p>即将到期团体会员</p>
27 <h2>{{ soonGuoqiMems }}</h2></div>
28 </div>
29
30 </el-col>
31 </el-row>
32
33 <h3 class="homeTitle">操作流程</h3>
34 <el-row class="wcard quickbtns" :gutter="20">
35 <el-col :span="8" @click="router.push('/member/list')">
36 <a>个人会员</a>
37 </el-col>
38 <el-col :span="8" @click="router.push('/group/list1')">
39 <a>团体会员</a>
40 </el-col>
41 <el-col :span="8" @click="router.push('/level/approval')">
42 <a>级位考试审核</a>
43 </el-col>
44 </el-row>
45
46 <el-row :gutter="20">
47 <el-col :span="8">
48 <h3 class="homeTitle">会员城市分布</h3>
49 <div class="wcard">
50 <div id="chart6" style="width: 100%;height: 300px" />
51 </div>
52 </el-col>
53 <el-col :span="8">
54 <h3 class="homeTitle">会员年龄段分布(人数)</h3>
55 <div class="wcard">
56 <div id="chart1" style="width: 100%;height: 300px" />
57 </div>
58 </el-col>
59 <el-col :span="8">
60 <site-message />
61 </el-col>
62 <el-col :span="8">
63 <h3 class="homeTitle">会员性别分布(人数)</h3>
64 <div class="wcard">
65 <div id="chart2" style="width: 100%;height: 300px" />
66 </div>
67 </el-col>
68 <el-col :span="8">
69 <h3 class="homeTitle">会员级位分布(人数)</h3>
70 <div class="wcard">
71 <div id="chart4" style="width: 100%;height: 300px" />
72 </div>
73 </el-col>
74 <el-col :span="8">
75 <h3 class="homeTitle">会员段位分布(人数)</h3>
76 <div class="wcard">
77 <div id="chart5" style="width: 100%;height: 300px" />
78 </div>
79 </el-col>
80
81 </el-row>
82 <el-dialog
83 v-model="dialogVisible"
84 title=" "
85 center
86 width="800px"
87 :show-close="false"
88 >
89 <div>
90 <span> <el-result style="padding: 0;" icon="warning" title="" /> </span>
91 </div>
92 <h1 style="text-align: center;">
93 会员即将过期,将会影响你的业务办理,请及时续费!
94 </h1>
95 <template #footer>
96 <el-row justify="center">
97 <el-button type="primary" @click="dialogVisible=false">确定</el-button>
98 </el-row>
99 </template>
100 </el-dialog>
101 <!-- 已过期 -->
102 <el-dialog
103 v-model="ShowDialog"
104 center
105 width="800px"
106 :show-close="false"
107 >
108 <div>
109 <span> <el-result style="padding: 0;" icon="warning" title="" /> </span>
110 </div>
111 <h1 style="text-align: center;">
112 会员已过期,将会影响你的业务办理,请及时续费!
113 </h1>
114 <template #footer>
115 <el-row justify="center">
116 <el-button type="primary" @click="goBack">确定</el-button>
117 </el-row>
118 </template>
119 </el-dialog>
120 </div>
121 </template>
122
123 <script setup name="Index">
124 import * as echarts from 'echarts'
125 import 'echarts-wordcloud'
126 import _ from 'lodash'
127 import { useRouter } from 'vue-router'
128 import { onMounted, onUnmounted, watch, ref } from 'vue'
129 import useAppStore from '@/store/modules/app'
130 import { ageRangeCount, sexRangeCount, levelRangeCount, rankRangeCount, memberCountMap, cityRangeCount } from '@/api/system/homePage'
131 import SiteMessage from '@/views/index/components/siteMessage'
132 import useUserStore from '@/store/modules/user'
133 const userStore = useUserStore()
134 const appStore = useAppStore()
135 const myCharts = []
136 const players = ref(0)
137 const members = ref(0)
138 const coach = ref(0)
139 const examiner = ref(0)
140 const router = useRouter()
141 const soonGuoqiPers = ref(0)
142 const soonGuoqiMems = ref(0)
143 const dialogVisible = ref(false)
144 const ShowDialog = ref(false)
145
146 onMounted(() => {
147 if (userStore.authenticationStatus != '2' && userStore.authenticationStatus != '4') {
148 if (userStore.authenticationStatus == 5) {
149 ShowDialog.value = true
150 } else {
151 perfectInfo()
152 }
153 } else {
154 if (userStore.authenticationStatus == '4') {
155 dialogVisible.value = true
156 }
157 getChart1()
158 getChart2()
159 getChart4()
160 getChart5()
161 getChart6()
162 getMemberCount()
163 window.onresize = _.debounce(myChartsResize, 150)
164 }
165 })
166
167 onUnmounted(() => {
168 window.onresize = null
169 _.each(myCharts, c => c.dispose())
170 })
171
172 // 去续费
173 function goBack() {
174 if (userStore.genFlag == 1) {
175 ShowDialog.value = false
176 } else {
177 // 跳转到续费页
178 router.push({
179 path: '/user/profile',
180 query: {
181 type: 2
182 }
183 })
184 }
185 }
186
187 watch(() => appStore.sidebar.opened, () => {
188 setTimeout(myChartsResize, 300)
189 })
190
191 function getMemberCount() {
192 memberCountMap().then(res => {
193 const map = res.data
194 players.value = map.players
195 members.value = map.members
196 coach.value = map.coach
197 examiner.value = map.examiner
198 soonGuoqiPers.value = map.soonExpired
199 soonGuoqiMems.value = map.soonMember
200 })
201 }
202
203
204 function myChartsResize() {
205 _.each(myCharts, c => c.resize())
206 }
207
208 async function getChart1() {
209 const result = await ageRangeCount()
210 const myData = result.data
211
212 const myChart = echarts.init(document.getElementById('chart1'))
213 const option = {
214 grid: {
215 left: '0',
216 right: '0',
217 bottom: '0',
218 top: '30',
219 containLabel: true,
220 show: true,
221 backgroundColor: '#fafbfd'
222 },
223 tooltip: {
224 trigger: 'axis'
225 },
226 calculable: true,
227 xAxis: [
228 {
229 type: 'category',
230 data: ['3-6 岁', '7-14 岁', '15-18 岁', '18 岁以上']
231 }
232 ],
233 yAxis: [{ type: 'value' }],
234 series: [
235 {
236 name: '会员人数',
237 type: 'pictorialBar',
238 symbol: 'roundRect',
239 symbolSize: [30, 5],
240 symbolRepeat: true,
241 symbolClip: false,
242 itemStyle: {
243 shadowColor: 'rgba(0, 0, 0, 0.3)',
244 shadowBlur: 18,
245 borderColor: '#fff',
246 borderWidth: 1,
247 color: {
248 type: 'linear',
249 x: 0,
250 y: 0,
251 x2: 0,
252 y2: 1,
253 colorStops: [{
254 offset: 0, color: '#0091ea' // 0% 处的颜色
255 }, {
256 offset: 1, color: '#36c6e1' // 100% 处的颜色
257 }],
258 globalCoord: false // 缺省为 false
259 }
260 },
261 data: myData
262 }
263 ]
264 }
265 myChart.setOption(option)
266 myCharts.push(myChart)
267 }
268 async function getChart2() {
269 const result = await sexRangeCount()
270 const myData = result.data
271
272 const myChart = echarts.init(document.getElementById('chart2'))
273 const option = {
274 color: [
275 {
276 type: 'linear',
277 x: 0,
278 y: 0,
279 x2: 0,
280 y2: 1,
281 colorStops: [{
282 offset: 0, color: 'RGBA(57, 160, 221, 1)' // 0% 处的颜色
283 }, {
284 offset: 1, color: 'RGBA(61, 147, 223, 1)' // 100% 处的颜色
285 }],
286 global: false // 缺省为 false
287 }, {
288 type: 'linear',
289 x: 0,
290 y: 0,
291 x2: 0,
292 y2: 1,
293 colorStops: [{
294 offset: 0, color: 'RGBA(240, 96, 153, 1)' // 0% 处的颜色
295 }, {
296 offset: 1, color: 'RGBA(252, 101, 122, 1)' // 100% 处的颜色
297 }],
298 global: false // 缺省为 false
299 }
300 ],
301 tooltip: {
302 trigger: 'item'
303 },
304 legend: {
305 left: 'right'
306 },
307 label: {
308 formatter: '{d}%',
309 fontSize: 20,
310 fontWeight: 'bold'
311 },
312 series: [
313 {
314 type: 'pie',
315 radius: ['40%', '70%'],
316 itemStyle: {
317 borderColor: '#fff',
318 borderWidth: 2,
319 shadowColor: 'rgba(0, 0, 0, 0.2)',
320 shadowBlur: 20
321 },
322 avoidLabelOverlap: false,
323 data: myData
324 }
325 ]
326 }
327 myChart.setOption(option)
328 myCharts.push(myChart)
329 }
330 async function getChart4() {
331 const result = await levelRangeCount()
332 const myData = result.data
333
334 const myChart = echarts.init(document.getElementById('chart4'))
335 const option = {
336 grid: {
337 left: '0',
338 right: '0',
339 bottom: '0',
340 top: '30',
341 containLabel: true,
342 show: true,
343 backgroundColor: '#fafbfd'
344 },
345 tooltip: {
346 trigger: 'axis'
347 },
348 color: [{
349 type: 'linear',
350 x: 0,
351 y: 0,
352 x2: 1,
353 y2: 1,
354 colorStops: [{
355 offset: 0, color: '#1DBDCD' // 0% 处的颜色
356 }, {
357 offset: 1, color: '#2CE8C7' // 100% 处的颜色
358 }],
359 global: false // 缺省为 false
360 }],
361 xAxis: { type: 'value' },
362 yAxis: {
363 type: 'category',
364 data: ['一级', '二级', '三级', '四级', '五级', '六级', '七级', '八级', '九级', '十级']
365 },
366 series: [{
367 type: 'bar',
368 itemStyle: {
369 borderWidth: 2,
370 borderColor: '#fff'
371 },
372 data: myData
373 }]
374 }
375 myChart.setOption(option)
376 myCharts.push(myChart)
377 }
378 async function getChart5() {
379 const result = await rankRangeCount()
380 const myData = result.data
381
382 const myChart = echarts.init(document.getElementById('chart5'))
383 const option = {
384 grid: {
385 left: '0',
386 right: '0',
387 bottom: '0',
388 top: '30',
389 containLabel: true,
390 show: true,
391 backgroundColor: '#fafbfd'
392 },
393 color: [{
394 type: 'linear',
395 x: 0,
396 y: 0,
397 x2: 1,
398 y2: 1,
399 colorStops: [{
400 offset: 0, color: '#3DA2DA' // 0% 处的颜色
401 }, {
402 offset: 1, color: '#4CC5F8' // 100% 处的颜色
403 }],
404 global: false // 缺省为 false
405 }],
406 tooltip: {
407 trigger: 'axis'
408 },
409 xAxis: { type: 'value' },
410 yAxis: {
411 type: 'category',
412 data: ['一段', '二段', '三段', '四段', '五段', '六段', '七段', '八段', '九段']
413 },
414 series: [{
415 type: 'bar',
416 itemStyle: {
417 borderWidth: 2,
418 borderColor: '#fff'
419 },
420 data: myData
421 }]
422 }
423 myChart.setOption(option)
424 myCharts.push(myChart)
425 }
426
427 function perfectInfo() {
428 router.replace({
429 path: '/perfect'
430 })
431 }
432
433
434 async function getChart6() {
435 const result = await cityRangeCount()
436 const myData = result.data
437
438 const myChart = echarts.init(document.getElementById('chart6'))
439 const option = {
440 textStyle: {
441 color: function() {
442 return 'rgb(' + [
443 Math.round(Math.random() * 160),
444 Math.round(Math.random() * 160),
445 Math.round(Math.random() * 160)
446 ].join(',') + ')'
447 }
448 },
449 series: [{
450 type: 'wordCloud',
451 data: myData
452 }]
453 }
454 myChart.setOption(option)
455 myCharts.push(myChart)
456 }
457
458 </script>
459
460
461 <style scoped lang="scss">
462 .card{
463 background: #FFFFFF;
464 border-radius: 10px;
465 }
466 .dataItem{display: flex;align-items: center;margin:20px 5%;
467 border-right: 1px solid #eee;
468 &:last-child{border-right: none;}
469 img{width: 55px;height: 55px;margin-right: 8%;}
470 p{font-size: 15px;color: #7B7F83;margin:0 0 10px;}
471 h2{color: #2B3133;font-size: 1.8vw;margin: 0}
472 }
473 .home {
474 background: RGBA(245, 247, 249, 1);
475 font-family: "open sans", "Helvetica Neue", Helvetica, Arial, sans-serif;
476 font-size: 13px;
477 color: #676a6c;
478 overflow-x: hidden;
479 ul {
480 padding: 0;
481 margin: 0;list-style-type: none;
482 }
483 }
484 .homeTitle{font-weight: 500;color: #2B3133;margin: 30px 0 15px;}
485 .fiveflex{display: flex;justify-content: space-between;
486 .fitem{width: 18%;border-radius: 3px;display: flex;align-items: center; padding: 16px 15px;
487 p{color: #fff;}
488 img{margin-right: 20%;}
489 }
490 .wcard{width: 18%;border-radius: 10px;}
491 .ctitle{border-left:2px solid #20C59D;line-height: 1;padding-left: 10px;color: #2B3133;}
492 .cbody{display: flex;
493 p{width: 50%;
494 color: #7B7F83;}
495 span{display: block;
496 color: #2B3133;
497 font-size: 26px;}
498 }
499 .wfitem{display: flex; align-items: center;
500 img{margin-right: 20px; width: 55px;height: 55px;}
501 p{color: #7B7F83;}
502 span{display: block;font-size: 26px;color: #2B3133;}
503 }
504 }
505 .fitem:nth-child(1){background: linear-gradient(270deg, #54E1B9, #00CAA6);}
506 .fitem:nth-child(2){background: linear-gradient(270deg, #BE8EFB, #A76DF4);}
507 .fitem:nth-child(3){background: linear-gradient(90deg, #FEA449, #FFB95F);}
508 .fitem:nth-child(4){background: linear-gradient(270deg, #5E9AF3, #4169EC);}
509 .fitem:nth-child(5){background: linear-gradient(90deg, #F83841, #F76D74);}
510 .wcard{background: #fff; padding:15px;overflow: hidden;position: relative;
511 .po-title{position: absolute;
512 h3{font-size: 18px;color: #2B3133;margin: 0;}
513 h2{color: #014A9F;font-size: 30px;margin: 6px 0;}
514 p{color: #7B7F83;font-size: 18px;margin: 0;}
515 }
516 }
517 .quickbtns{
518 a{display: block;text-align: center;
519 background: #E5EDF5;
520 height: 70px;line-height: 70px;text-overflow: ellipsis;
521 overflow: hidden;white-space: nowrap;
522 font-size: 20px;margin-bottom: 20px;
523 color: #014A9F;
524 border-radius: 10px;
525 &:hover{color: #FFFFFF;background: #014A9F;}
526 }
527 }
528
529 .topflex{display: flex;justify-content: space-between;}
530 .mb40{margin-bottom: 40px;}
531
532 @media (max-width: 1400px) {
533 .quickbtns{
534 a{ font-size: 18px;}
535 }
536 .dataItem{
537 p { font-size: 14px;}
538 }
539 }
540 @media (max-width: 1200px) {
541 .quickbtns{
542 a{ font-size: 16px;}
543 }
544 }
545 </style>
546
1 <template>
2 <div class="app-container home" :hidden="userStore.hasMember == '0'">
3 <h3 class="homeTitle">操作入口</h3>
4 <el-row class="wcard quickbtns" :gutter="20">
5 <el-col :span="5" @click="router.push('/member/addMember')">
6 <a>添加会员</a>
7 </el-col>
8 <el-col :span="5" @click="router.push('/member/memberPay')">
9 <a>会员缴费</a>
10 </el-col>
11 <el-col :span="5" @click="router.push('/member/list')">
12 <a>会员列表</a>
13 </el-col>
14 <el-col :span="5" @click="router.push('/level/apply')">
15 <a>级位考试申请</a>
16 </el-col>
17 <el-col :span="4" @click="router.push('/member/mobillize')">
18 <a>会员调动</a>
19 </el-col>
20 </el-row>
21
22 <el-row :gutter="20">
23 <el-col :span="8">
24 <h3 class="homeTitle">会员年龄段分布(人数)</h3>
25 <div class="wcard">
26 <div id="chart1" style="width: 100%;height: 300px" />
27 </div>
28 </el-col>
29 <el-col :span="8">
30 <h3 class="homeTitle">会员性别分布(人数)</h3>
31 <div class="wcard">
32 <div id="chart2" style="width: 100%;height: 300px" />
33 </div>
34 </el-col>
35 <el-col :span="8">
36 <h3 class="homeTitle">会员分布</h3>
37 <div class="wcard">
38 <div id="chart3" style="width: 100%;height: 300px" />
39 </div>
40 </el-col>
41 <el-col :span="8">
42 <h3 class="homeTitle">会员级位分布(人数)</h3>
43 <div class="wcard">
44 <div id="chart4" style="width: 100%;height: 300px" />
45 </div>
46 </el-col>
47 <el-col :span="8">
48 <h3 class="homeTitle">会员段位分布(人数)</h3>
49 <div class="wcard">
50 <div id="chart5" style="width: 100%;height: 300px" />
51 </div>
52 </el-col>
53 <el-col :span="8">
54 <site-message />
55 </el-col>
56 </el-row>
57
58 <el-dialog
59 v-model="dialogVisible"
60 center
61 width="800px"
62 >
63 <div>
64 <span> <el-result style="padding: 0;" icon="warning" title="" /> </span>
65 </div>
66 <h1 style="text-align: center;">
67 {{ title }}
68 </h1>
69 <template #footer>
70 <el-row justify="center">
71 <el-button type="primary" @click="dialogVisible=false">确定</el-button>
72 </el-row>
73 </template>
74 </el-dialog>
75
76 <!-- 已过期 -->
77 <el-dialog
78 v-model="ShowDialog"
79 center
80 width="800px"
81 :show-close="false"
82 >
83 <div>
84 <span> <el-result style="padding: 0;" icon="warning" title="" /> </span>
85 </div>
86 <h1 style="text-align: center;">
87 {{ title }}
88 </h1>
89 <template #footer>
90 <el-row justify="center">
91 <el-button type="primary" @click="goBack">确定</el-button>
92 </el-row>
93 </template>
94 </el-dialog>
95 </div>
96 </template>
97
98 <script setup name="Index">
99 import * as echarts from 'echarts'
100 import _ from 'lodash'
101 import { onMounted, onUnmounted, watch, ref } from 'vue'
102 import useAppStore from '@/store/modules/app'
103 import { useRouter } from 'vue-router'
104 import useUserStore from '@/store/modules/user'
105 import { ageRangeCount, sexRangeCount, levelRangeCount, rankRangeCount, clubMemRangeCount } from '@/api/system/homePage'
106 import SiteMessage from '@/views/index/components/siteMessage'
107
108 const userStore = useUserStore()
109 const router = useRouter()
110 const title = ref('请先去完善团体信息')
111 const appStore = useAppStore()
112 const myCharts = []
113 const dialogVisible = ref(false)
114 const ShowDialog = ref(false)
115
116
117 onMounted(() => {
118 if (userStore.authenticationStatus != '2' && userStore.authenticationStatus != '4') {
119 if (userStore.authenticationStatus == 5) {
120 userStore.genFlag != 1 ? title.value = '您的会员已过期,将会影响你的业务办理,请及时续费!' : title.value = '您的会员已过期!'
121 ShowDialog.value = true
122 } else {
123 perfectInfo()
124 }
125 } else {
126 if (userStore.authenticationStatus == '4') {
127 dialogVisible.value = true
128 title.value = '你的会员即将过期,将会影响你的业务,请及时续费!'
129 }
130
131 getChart1()
132 getChart2()
133 getChart3()
134 getChart4()
135 getChart5()
136 window.onresize = _.debounce(myChartsResize, 150)
137 }
138 })
139
140 onUnmounted(() => {
141 window.onresize = null
142 _.each(myCharts, c => c.dispose())
143 })
144
145 watch(() => appStore.sidebar.opened, () => {
146 setTimeout(myChartsResize, 300)
147 })
148
149 function myChartsResize() {
150 _.each(myCharts, c => c.resize())
151 }
152
153 // 去续费
154 function goBack() {
155 if (userStore.genFlag == 1) {
156 ShowDialog.value = false
157 } else {
158 // 跳转到续费页
159 router.push({
160 path: '/user/profile',
161 query: {
162 type: 2
163 }
164 })
165 }
166 }
167
168
169 async function getChart1() {
170 const result = await ageRangeCount()
171 const myData = result.data
172
173 const myChart = echarts.init(document.getElementById('chart1'))
174 const option = {
175 grid: {
176 left: '0',
177 right: '0',
178 bottom: '0',
179 top: '30',
180 containLabel: true,
181 show: true,
182 backgroundColor: '#fafbfd'
183 },
184 tooltip: {
185 trigger: 'axis'
186 },
187 calculable: true,
188 xAxis: [
189 {
190 type: 'category',
191 data: ['3-6 岁', '7-14 岁', '15-18 岁', '18 岁以上']
192 }
193 ],
194 yAxis: [{ type: 'value' }],
195 series: [
196 {
197 name: '会员人数',
198 type: 'pictorialBar',
199 symbol: 'roundRect',
200 symbolSize: [30, 5],
201 symbolRepeat: true,
202 symbolClip: false,
203 itemStyle: {
204 shadowColor: 'rgba(0, 0, 0, 0.3)',
205 shadowBlur: 18,
206 borderColor: '#fff',
207 borderWidth: 1,
208 color: {
209 type: 'linear',
210 x: 0,
211 y: 0,
212 x2: 0,
213 y2: 1,
214 colorStops: [{
215 offset: 0, color: '#0091ea' // 0% 处的颜色
216 }, {
217 offset: 1, color: '#36c6e1' // 100% 处的颜色
218 }],
219 globalCoord: false // 缺省为 false
220 }
221 },
222 data: myData
223 }
224 ]
225 }
226 myChart.setOption(option)
227 myCharts.push(myChart)
228 }
229 async function getChart2() {
230 const result = await sexRangeCount()
231 const myData = result.data
232
233 const myChart = echarts.init(document.getElementById('chart2'))
234 const option = {
235 color: [
236 {
237 type: 'linear',
238 x: 0,
239 y: 0,
240 x2: 0,
241 y2: 1,
242 colorStops: [{
243 offset: 0, color: 'RGBA(57, 160, 221, 1)' // 0% 处的颜色
244 }, {
245 offset: 1, color: 'RGBA(61, 147, 223, 1)' // 100% 处的颜色
246 }],
247 global: false // 缺省为 false
248 }, {
249 type: 'linear',
250 x: 0,
251 y: 0,
252 x2: 0,
253 y2: 1,
254 colorStops: [{
255 offset: 0, color: 'RGBA(240, 96, 153, 1)' // 0% 处的颜色
256 }, {
257 offset: 1, color: 'RGBA(252, 101, 122, 1)' // 100% 处的颜色
258 }],
259 global: false // 缺省为 false
260 }
261 ],
262 tooltip: {
263 trigger: 'item'
264 },
265 legend: {
266 left: 'right'
267 },
268 label: {
269 formatter: '{d}%',
270 fontSize: 20,
271 fontWeight: 'bold'
272 },
273 series: [
274 {
275 type: 'pie',
276 radius: ['40%', '70%'],
277 itemStyle: {
278 borderColor: '#fff',
279 borderWidth: 2,
280 shadowColor: 'rgba(0, 0, 0, 0.2)',
281 shadowBlur: 20
282 },
283 avoidLabelOverlap: false,
284 data: myData
285 }
286 ]
287 }
288 myChart.setOption(option)
289 myCharts.push(myChart)
290 }
291 async function getChart3() {
292 // const myData = [
293 // { value: 45, name: '有效会员' },
294 // { value: 20, name: '过期会员' },
295 // { value: 55, name: '即将过期会员' }
296 // ]
297 const res = await clubMemRangeCount()
298 const myData = res.data
299
300 const myChart = echarts.init(document.getElementById('chart3'))
301 const option = {
302 color: [
303 {
304 type: 'linear',
305 x: 0,
306 y: 0,
307 x2: 0,
308 y2: 1,
309 colorStops: [{
310 offset: 0, color: 'rgb(35,203,203)' // 0% 处的颜色
311 }, {
312 offset: 1, color: 'rgb(44,232,199)' // 100% 处的颜色
313 }],
314 global: false // 缺省为 false
315 },
316 {
317 type: 'linear',
318 x: 0,
319 y: 0,
320 x2: 0,
321 y2: 1,
322 colorStops: [{
323 offset: 0, color: 'RGBA(57, 160, 221, 1)' // 0% 处的颜色
324 }, {
325 offset: 1, color: 'RGBA(61, 147, 223, 1)' // 100% 处的颜色
326 }],
327 global: false // 缺省为 false
328 }, {
329 type: 'linear',
330 x: 0,
331 y: 0,
332 x2: 0,
333 y2: 1,
334 colorStops: [{
335 offset: 0, color: 'RGBA(240, 96, 153, 1)' // 0% 处的颜色
336 }, {
337 offset: 1, color: 'RGBA(252, 101, 122, 1)' // 100% 处的颜色
338 }],
339 global: false // 缺省为 false
340 }
341 ],
342 tooltip: {
343 trigger: 'item'
344 },
345 legend: {
346 left: 'right'
347 },
348 label: {
349 formatter: '{d}%',
350 fontSize: 20,
351 fontWeight: 'bold'
352 },
353 series: [
354 {
355 type: 'pie',
356 radius: ['40%', '70%'],
357 itemStyle: {
358 borderColor: '#fff',
359 borderWidth: 2,
360 shadowColor: 'rgba(0, 0, 0, 0.2)',
361 shadowBlur: 20
362 },
363 avoidLabelOverlap: false,
364 data: myData
365 }
366 ]
367 }
368 myChart.setOption(option)
369 myCharts.push(myChart)
370 }
371 async function getChart4() {
372 const result = await levelRangeCount()
373 const myData = result.data
374
375 const myChart = echarts.init(document.getElementById('chart4'))
376 const option = {
377 grid: {
378 left: '0',
379 right: '0',
380 bottom: '0',
381 top: '30',
382 containLabel: true,
383 show: true,
384 backgroundColor: '#fafbfd'
385 },
386 tooltip: {
387 trigger: 'axis'
388 },
389 color: [{
390 type: 'linear',
391 x: 0,
392 y: 0,
393 x2: 1,
394 y2: 1,
395 colorStops: [{
396 offset: 0, color: '#1DBDCD' // 0% 处的颜色
397 }, {
398 offset: 1, color: '#2CE8C7' // 100% 处的颜色
399 }],
400 global: false // 缺省为 false
401 }],
402 xAxis: { type: 'value' },
403 yAxis: {
404 type: 'category',
405 data: ['一级', '二级', '三级', '四级', '五级', '六级', '七级', '八级', '九级', '十级']
406 },
407 series: [{
408 type: 'bar',
409 itemStyle: {
410 borderWidth: 2,
411 borderColor: '#fff'
412 },
413 data: myData
414 }]
415 }
416 myChart.setOption(option)
417 myCharts.push(myChart)
418 }
419 async function getChart5() {
420 const result = await rankRangeCount()
421 const myData = result.data
422
423 const myChart = echarts.init(document.getElementById('chart5'))
424 const option = {
425 grid: {
426 left: '0',
427 right: '0',
428 bottom: '0',
429 top: '30',
430 containLabel: true,
431 show: true,
432 backgroundColor: '#fafbfd'
433 },
434 color: [{
435 type: 'linear',
436 x: 0,
437 y: 0,
438 x2: 1,
439 y2: 1,
440 colorStops: [{
441 offset: 0, color: '#3DA2DA' // 0% 处的颜色
442 }, {
443 offset: 1, color: '#4CC5F8' // 100% 处的颜色
444 }],
445 global: false // 缺省为 false
446 }],
447 tooltip: {
448 trigger: 'axis'
449 },
450 xAxis: { type: 'value' },
451 yAxis: {
452 type: 'category',
453 data: ['一段', '二段', '三段', '四段', '五段', '六段', '七段', '八段', '九段']
454 },
455 series: [{
456 type: 'bar',
457 itemStyle: {
458 borderWidth: 2,
459 borderColor: '#fff'
460 },
461 data: myData
462 }]
463 }
464 myChart.setOption(option)
465 myCharts.push(myChart)
466 }
467
468 function goUser() {
469 router.push({
470 path: '/user/profile'
471 })
472 }
473
474 function perfectInfo() {
475 router.replace({
476 path: '/perfect'
477 })
478 }
479
480 </script>
481
482
483 <style scoped lang="scss">
484 .card{
485 background: #FFFFFF;
486 border-radius: 10px;
487 }
488 .dataItem{display: flex;align-items: center;margin:20px 5%;
489 border-right: 1px solid #eee;
490 &:last-child{border-right: none;}
491 img{width: 55px;height: 55px;margin-right: 8%;}
492 p{font-size: 15px;color: #7B7F83;margin:0 0 10px;}
493 h2{color: #2B3133;font-size: 1.8vw;margin: 0}
494 }
495 .home {
496 background: RGBA(245, 247, 249, 1);
497 font-family: "open sans", "Helvetica Neue", Helvetica, Arial, sans-serif;
498 font-size: 13px;
499 color: #676a6c;
500 overflow-x: hidden;
501 ul {
502 padding: 0;
503 margin: 0;list-style-type: none;
504 }
505 }
506 .homeTitle{font-weight: 500;color: #2B3133;margin: 30px 0 15px;}
507 .fiveflex{display: flex;justify-content: space-between;
508 .fitem{width: 18%;border-radius: 3px;display: flex;align-items: center; padding: 16px 15px;
509 p{color: #fff;}
510 img{margin-right: 20%;}
511 }
512 .wcard{width: 18%;border-radius: 10px;}
513 .ctitle{border-left:2px solid #20C59D;line-height: 1;padding-left: 10px;color: #2B3133;}
514 .cbody{display: flex;
515 p{width: 50%;
516 color: #7B7F83;}
517 span{display: block;
518 color: #2B3133;
519 font-size: 26px;}
520 }
521 .wfitem{display: flex; align-items: center;
522 img{margin-right: 20px; width: 55px;height: 55px;}
523 p{color: #7B7F83;}
524 span{display: block;font-size: 26px;color: #2B3133;}
525 }
526 }
527 .fitem:nth-child(1){background: linear-gradient(270deg, #54E1B9, #00CAA6);}
528 .fitem:nth-child(2){background: linear-gradient(270deg, #BE8EFB, #A76DF4);}
529 .fitem:nth-child(3){background: linear-gradient(90deg, #FEA449, #FFB95F);}
530 .fitem:nth-child(4){background: linear-gradient(270deg, #5E9AF3, #4169EC);}
531 .fitem:nth-child(5){background: linear-gradient(90deg, #F83841, #F76D74);}
532 .wcard{background: #fff; padding:15px;overflow: hidden;position: relative;
533 .po-title{position: absolute;
534 h3{font-size: 18px;color: #2B3133;margin: 0;}
535 h2{color: #014A9F;font-size: 30px;margin: 6px 0;}
536 p{color: #7B7F83;font-size: 18px;margin: 0;}
537 }
538 }
539 .quickbtns{
540 a{display: block;text-align: center;
541 background: #E5EDF5;
542 height: 70px;line-height: 70px;text-overflow: ellipsis;
543 overflow: hidden;white-space: nowrap;
544 font-size: 20px;margin-bottom: 20px;
545 color: #014A9F;
546 border-radius: 10px;
547 &:hover{color: #FFFFFF;background: #014A9F;}
548 }
549 }
550
551 .topflex{display: flex;justify-content: space-between;}
552 .mb40{margin-bottom: 40px;}
553
554 @media (max-width: 1400px) {
555 .quickbtns{
556 a{ font-size: 18px;}
557 }
558 .dataItem{
559 p { font-size: 14px;}
560 }
561 }
562 @media (max-width: 1200px) {
563 .quickbtns{
564 a{ font-size: 16px;}
565 }
566 }
567 </style>
568
1 <template>
2 <div>
3 <h3 class="homeTitle">待办提醒<router-link class="fr" to="/messages">更多<el-icon><ArrowRight /></el-icon></router-link></h3>
4 <div class="wcard">
5 <ul class="mesUl" :style="`height: ${mesHeight}px`">
6 <li v-for="item in messageList" :key="item.id" :class="{'done':item.readFlag=='1'}" @click="readMessage(item)">
7 <div>{{ item.name }}</div>
8 <span class="date">{{ parseTime(item.createTime,'{m}-{d} {h}:{i}') }}</span>
9 </li>
10 <li v-if="messageList?.length<=0" class="done">
11 暂无代办业务!
12 </li>
13 </ul>
14 </div>
15 </div>
16 </template>
17
18 <script setup>
19 import { onMounted, ref } from 'vue'
20 import { getMessage, reader } from '@/api/system/homePage'
21 import _ from 'lodash'
22 import { useRouter } from 'vue-router'
23
24 const router = useRouter()
25 const messageList = ref([])
26
27 defineProps({
28 mesHeight: {
29 type: Number,
30 default: 300
31 }
32 })
33
34 onMounted(() => {
35 getMessageList()
36 })
37
38 async function getMessageList() {
39 const res = await getMessage({
40 pageNum: 1,
41 pageSize: 10
42 })
43
44 _.each(res.rows, (d) => {
45 switch (d.type) {
46 case 30001:
47 d.name = '你有一条会员缴费等待审批,点击去处理!'
48 d.path = '/member/audit'
49 break
50 case 30002:
51 d.name = '你有一条级位考试等待审批,点击去处理!'
52 d.path = '/level/approval'
53 break
54 case 30003:
55 d.name = '你有一条段位考试等待审批,点击去处理!'
56 d.path = '/rank/approval'
57 break
58 case 30004:
59 d.name = '你有一条会员调动等待审批,点击去处理!'
60 d.path = '/member/mobillize'
61 break
62 case 30005:
63 d.name = '你有一条团体会员认证等待审批,点击去处理!'
64 d.path = '/group/authentication'
65 break
66 case 30006:
67 d.name = '你有一条段位成绩等待审批,点击去处理!'
68 d.path = '/rank/score/approval'
69 break
70 case 40001:
71 d.name = '你有一条级位申请待提交,点击去处理!'
72 d.path = '/level/apply/modify/' + d.eventId
73 break
74 case 40002:
75 d.name = '你有一条段位申请待提交,点击去处理!'
76 d.path = '/rank/apply/modify/' + d.eventId
77 break
78 case 40003:
79 d.name = '你有一条成绩维护的数据待提交,点击去处理!'
80 d.path = '/rank/score/modify/' + d.eventId
81 break
82 case 50001:
83 d.name = '你有一条新的个人会员申请,点击去处理!'
84 d.path = '/member/list'
85 break
86 }
87 })
88 messageList.value = res.rows
89 }
90
91 async function readMessage(item) {
92 await router.push(item.path)
93 await reader({ id: item.id })
94 item.readFlag = '1'
95 }
96
97 </script>
98
99 <style scoped lang="scss">
100 .homeTitle{font-weight: 500;color: #2B3133;margin: 30px 0 15px;}
101 .wcard{background: #fff; padding:15px;overflow: hidden;position: relative;
102 .po-title{position: absolute;
103 h3{font-size: 18px;color: #2B3133;margin: 0;}
104 h2{color: #014A9F;font-size: 30px;margin: 6px 0;}
105 p{color: #7B7F83;font-size: 18px;margin: 0;}
106 }
107 }
108 .home {
109 background: RGBA(245, 247, 249, 1);
110 font-family: "open sans", "Helvetica Neue", Helvetica, Arial, sans-serif;
111 font-size: 13px;
112 color: #676a6c;
113 overflow-x: hidden;
114 ul {
115 padding: 0;
116 margin: 0;list-style-type: none;
117 }
118 }
119 .mesUl{
120 overflow: auto;
121 li{ position: relative;line-height: 45px;padding-left: 40px;display: flex;justify-content: space-between;
122 color: #666;cursor: pointer;
123 &>div{width: 80%;overflow: hidden;text-overflow: ellipsis;white-space: nowrap; font-size: 16px;}
124 &:before{width: 6px;content: '';
125 height: 6px;position: absolute;left: 20px;top: 0;bottom: 0;margin: auto;
126 background: var(--el-color-primary);
127 border-radius: 50%;}
128 &:hover{background: #f4f4f4;}
129 .link{display: inline-block;}
130 .date{font-size: 12px;float: right;color: #999;width: 20%;text-align: right;padding-right: 15px; min-width: 80px}
131 }
132 li.done{&:before{background: #ddd;}}
133 }
134 </style>
1 <template>
2 <div class="app-container">
3 <div class="wcard">
4 <ul class="mesUl">
5 <li v-for="item in messageList" :key="item.id" :class="{'done':item.readFlag=='1'}" @click="readMessage(item)">
6 <div>{{ item.name }}</div>
7 <span class="date">{{ item.createTime }}</span>
8 </li>
9 <li v-if="messageList.length<=0" class="done">
10 暂无代办业务!
11 </li>
12 </ul>
13 <pagination
14 v-show="total > 0"
15 v-model:page="queryParams.pageNum"
16 v-model:limit="queryParams.pageSize"
17 :page-sizes="[15,30,45,60]"
18 :total="total"
19 @pagination="getMessageList"
20 />
21 </div>
22 </div>
23 </template>
24
25 <script setup name="Messages">
26 import { onMounted, reactive, ref } from 'vue'
27 import { getMessage, reader } from '@/api/system/homePage'
28 import _ from 'lodash'
29 import { useRouter } from 'vue-router'
30
31 const router = useRouter()
32 const messageList = ref([])
33 const queryParams = reactive({
34 pageNum: 1,
35 pageSize: 10
36 })
37 const total = ref(0)
38
39
40 onMounted(() => {
41 getMessageList()
42 })
43
44 async function getMessageList() {
45 const res = await getMessage(queryParams)
46
47 _.each(res.rows, (d) => {
48 switch (d.type) {
49 case 30001:
50 d.name = '你有一条会员缴费等待审批,点击去处理!'
51 d.path = '/member/audit'
52 break
53 case 30002:
54 d.name = '你有一条级位考试等待审批,点击去处理!'
55 d.path = '/level/approval'
56 break
57 case 30003:
58 d.name = '你有一条段位考试等待审批,点击去处理!'
59 d.path = '/rank/approval'
60 break
61 case 30004:
62 d.name = '你有一条会员调动等待审批,点击去处理!'
63 d.path = '/member/mobillize'
64 break
65 case 30005:
66 d.name = '你有一条团体会员认证等待审批,点击去处理!'
67 d.path = '/member/audit'
68 break
69 case 30006:
70 d.name = '你有一条段位成绩等待审批,点击去处理!'
71 d.path = '/rank/score/approval'
72 break
73 case 40001:
74 d.name = '你有一条级位申请待提交,点击去处理!'
75 d.path = '/level/apply/modify/:examId'
76 break
77 case 40002:
78 d.name = '你有一条段位位申请待提交,点击去处理!'
79 d.path = '/rank/apply/modify/:examId'
80 break
81 }
82 })
83 messageList.value = res.rows
84 total.value = res.total
85 }
86
87 async function readMessage(item) {
88 await router.push(item.path)
89 await reader({ id: item.id })
90 item.readFlag = '1'
91 }
92
93 </script>
94
95 <style scoped lang="scss">
96 .wcard{background: #fff; padding:15px;overflow: hidden;position: relative;
97 .po-title{position: absolute;
98 h3{font-size: 18px;color: #2B3133;margin: 0;}
99 h2{color: #014A9F;font-size: 30px;margin: 6px 0;}
100 p{color: #7B7F83;font-size: 18px;margin: 0;}
101 }
102 }
103 .mesUl{
104 li{ position: relative;line-height: 45px;padding-left: 40px;display: flex;justify-content: space-between;
105 color: #666;cursor: pointer;
106 &>div{width: 80%;overflow: hidden;text-overflow: ellipsis;white-space: nowrap; font-size: 16px;}
107 &:before{width: 6px;content: '';
108 height: 6px;position: absolute;left: 20px;top: 0;bottom: 0;margin: auto;
109 background: var(--el-color-primary);
110 border-radius: 50%;}
111 &:hover{background: #f4f4f4;}
112 .link{display: inline-block;}
113 .date{font-size: 12px;float: right;color: #999;width: 20%;text-align: right;padding-right: 15px;}
114 }
115 li.done{&:before{background: #f4f4f4;}}
116 }
117 </style>
1 <template>
2 <div class="app-container home">
3 <el-row class="card">
4 <el-col :span="5">
5 <div class="dataItem">
6 <div>
7 <p>个人会员</p>
8 <h2>{{ players }}</h2>
9 </div>
10 </div>
11 </el-col>
12 <el-col :span="5">
13 <div class="dataItem">
14 <div><p>团体会员</p>
15 <h2>{{ members }}</h2></div>
16 </div>
17 </el-col>
18 <el-col :span="5">
19 <div class="dataItem">
20 <div><p>二级协会</p>
21 <h2>{{ secondMembers }}</h2></div>
22 </div>
23 </el-col>
24 <el-col :span="5">
25 <div class="dataItem">
26 <div><p>即将到期会员</p>
27 <h2>{{ soonGuoqiPers }}</h2></div>
28 </div>
29 </el-col>
30 <el-col :span="4">
31 <div class="dataItem">
32 <div><p>即将到期团体会员</p>
33 <h2>{{ soonGuoqiMems }}</h2></div>
34 </div>
35
36 </el-col>
37 </el-row>
38 <h3 class="homeTitle">操作流程</h3>
39 <el-row class="wcard quickbtns" :gutter="20">
40 <el-col :span="5" @click="router.push('/member/audit')">
41 <a>缴费审核</a>
42 </el-col>
43 <el-col :span="5" @click="router.push('/level/approval')">
44 <a>级位考试审核</a>
45 </el-col>
46 <el-col :span="5" @click="router.push('/rank/apply')">
47 <a>段位考试申请</a>
48 </el-col>
49 <el-col :span="5" @click="router.push('/level/download')">
50 <a>级位考试证书确认</a>
51 </el-col>
52 <el-col :span="4" @click="router.push('/rank/download')">
53 <a>段位考试证书确认</a>
54 </el-col>
55 </el-row>
56
57 <el-row :gutter="20">
58 <el-col :span="8">
59 <h3 class="homeTitle">会员城市分布</h3>
60 <div class="wcard">
61 <div id="chart6" style="width: 100%;height: 300px" />
62 </div>
63 </el-col>
64 <el-col :span="8">
65 <h3 class="homeTitle">会员年龄段分布(人数)</h3>
66 <div class="wcard">
67 <div id="chart1" style="width: 100%;height: 300px" />
68 </div>
69 </el-col>
70 <el-col :span="8">
71 <site-message />
72 </el-col>
73 <el-col :span="8">
74 <h3 class="homeTitle">会员性别分布(人数)</h3>
75 <div class="wcard">
76 <div id="chart2" style="width: 100%;height: 300px" />
77 </div>
78 </el-col>
79 <el-col :span="8">
80 <h3 class="homeTitle">会员级位分布(人数)</h3>
81 <div class="wcard">
82 <div id="chart4" style="width: 100%;height: 300px" />
83 </div>
84 </el-col>
85 <el-col :span="8">
86 <h3 class="homeTitle">会员段位分布(人数)</h3>
87 <div class="wcard">
88 <div id="chart5" style="width: 100%;height: 300px" />
89 </div>
90 </el-col>
91
92 </el-row>
93
94 <el-dialog
95 v-model="dialogVisible"
96 center
97 width="800px"
98 :show-close="false"
99 >
100 <div>
101 <span> <el-result style="padding: 0;" icon="warning" title="" /> </span>
102 </div>
103 <h1 style="text-align: center;">
104 会员即将过期,将会影响你的业务办理,请及时续费!
105 </h1>
106 <template #footer>
107 <el-row justify="center">
108 <el-button type="primary" @click="dialogVisible=false">确定</el-button>
109 </el-row>
110 </template>
111 </el-dialog>
112
113 <!-- 已过期 -->
114 <el-dialog
115 v-model="ShowDialog"
116 center
117 width="800px"
118 :show-close="false"
119 >
120 <div>
121 <span> <el-result style="padding: 0;" icon="warning" title="" /> </span>
122 </div>
123 <h1 style="text-align: center;">
124 会员已过期,将会影响你的业务办理,请及时续费!
125 </h1>
126 <template #footer>
127 <el-row justify="center">
128 <el-button type="primary" @click="goBack">确定</el-button>
129 </el-row>
130 </template>
131 </el-dialog>
132 </div>
133 </template>
134
135 <script setup name="Index">
136 import * as echarts from 'echarts'
137 import 'echarts-wordcloud'
138 import _ from 'lodash'
139 import { useRouter } from 'vue-router'
140 import { onMounted, onUnmounted, watch, ref } from 'vue'
141 import useAppStore from '@/store/modules/app'
142 import { ageRangeCount, sexRangeCount, levelRangeCount, rankRangeCount, cityRangeCount, memberCountMap } from '@/api/system/homePage'
143 import SiteMessage from '@/views/index/components/siteMessage'
144 import useUserStore from '@/store/modules/user'
145
146 const userStore = useUserStore()
147 const router = useRouter()
148 const appStore = useAppStore()
149 const myCharts = []
150 const players = ref(0)
151 const members = ref(0)
152 const coach = ref(0)
153 const examiner = ref(0)
154 const soonGuoqiPers = ref(0)
155 const soonGuoqiMems = ref(0)
156 const secondMembers = ref(0)
157 const dialogVisible = ref(false)
158 const ShowDialog = ref(false)
159 onMounted(() => {
160 if (userStore.authenticationStatus != '2' && userStore.authenticationStatus != '4') {
161 if (userStore.authenticationStatus == 5) {
162 ShowDialog.value = true
163 } else {
164 perfectInfo()
165 }
166 } else {
167 if (userStore.authenticationStatus == '4') {
168 dialogVisible.value = true
169 }
170 getChart1()
171 getChart2()
172 getChart4()
173 getChart5()
174 getChart6()
175 getMemberCount()
176 window.onresize = _.debounce(myChartsResize, 150)
177 }
178 })
179
180 // 去续费
181 function goBack() {
182 if (userStore.genFlag == 1) {
183 ShowDialog.value = false
184 } else {
185 // 跳转到续费页
186 router.push({
187 path: '/user/profile',
188 query: {
189 type: 2
190 }
191 })
192 }
193 }
194
195 function perfectInfo() {
196 router.replace({
197 path: '/perfect'
198 })
199 }
200
201
202 onUnmounted(() => {
203 window.onresize = null
204 _.each(myCharts, c => c.dispose())
205 })
206
207 watch(() => appStore.sidebar.opened, () => {
208 setTimeout(myChartsResize, 300)
209 })
210
211 function getMemberCount() {
212 memberCountMap().then(res => {
213 const map = res.data
214 players.value = map.players
215 members.value = map.members
216 coach.value = map.coach
217 examiner.value = map.examiner
218 soonGuoqiPers.value = map.soonExpired
219 soonGuoqiMems.value = map.soonMember
220 secondMembers.value = map.secondMember
221 })
222 }
223
224 function myChartsResize() {
225 _.each(myCharts, c => c.resize())
226 }
227
228 async function getChart1() {
229 const result = await ageRangeCount()
230 const myData = result.data
231
232 const myChart = echarts.init(document.getElementById('chart1'))
233 const option = {
234 grid: {
235 left: '0',
236 right: '0',
237 bottom: '0',
238 top: '30',
239 containLabel: true,
240 show: true,
241 backgroundColor: '#fafbfd'
242 },
243 tooltip: {
244 trigger: 'axis'
245 },
246 calculable: true,
247 xAxis: [
248 {
249 type: 'category',
250 data: ['3-6 岁', '7-14 岁', '15-18 岁', '18 岁以上']
251 }
252 ],
253 yAxis: [{ type: 'value' }],
254 series: [
255 {
256 name: '会员人数',
257 type: 'pictorialBar',
258 symbol: 'roundRect',
259 symbolSize: [30, 5],
260 symbolRepeat: true,
261 symbolClip: false,
262 itemStyle: {
263 shadowColor: 'rgba(0, 0, 0, 0.3)',
264 shadowBlur: 18,
265 borderColor: '#fff',
266 borderWidth: 1,
267 color: {
268 type: 'linear',
269 x: 0,
270 y: 0,
271 x2: 0,
272 y2: 1,
273 colorStops: [{
274 offset: 0, color: '#0091ea' // 0% 处的颜色
275 }, {
276 offset: 1, color: '#36c6e1' // 100% 处的颜色
277 }],
278 globalCoord: false // 缺省为 false
279 }
280 },
281 data: myData
282 }
283 ]
284 }
285 myChart.setOption(option)
286 myCharts.push(myChart)
287 }
288 async function getChart2() {
289 // const myData = [
290 // { value: 45, name: '男' },
291 // { value: 55, name: '女' }
292 // ]
293 const result = await sexRangeCount()
294 const myData = result.data
295
296 const myChart = echarts.init(document.getElementById('chart2'))
297 const option = {
298 color: [
299 {
300 type: 'linear',
301 x: 0,
302 y: 0,
303 x2: 0,
304 y2: 1,
305 colorStops: [{
306 offset: 0, color: 'RGBA(57, 160, 221, 1)' // 0% 处的颜色
307 }, {
308 offset: 1, color: 'RGBA(61, 147, 223, 1)' // 100% 处的颜色
309 }],
310 global: false // 缺省为 false
311 }, {
312 type: 'linear',
313 x: 0,
314 y: 0,
315 x2: 0,
316 y2: 1,
317 colorStops: [{
318 offset: 0, color: 'RGBA(240, 96, 153, 1)' // 0% 处的颜色
319 }, {
320 offset: 1, color: 'RGBA(252, 101, 122, 1)' // 100% 处的颜色
321 }],
322 global: false // 缺省为 false
323 }
324 ],
325 tooltip: {
326 trigger: 'item'
327 },
328 legend: {
329 left: 'right'
330 },
331 label: {
332 formatter: '{d}%',
333 fontSize: 20,
334 fontWeight: 'bold'
335 },
336 series: [
337 {
338 type: 'pie',
339 radius: ['40%', '70%'],
340 itemStyle: {
341 borderColor: '#fff',
342 borderWidth: 2,
343 shadowColor: 'rgba(0, 0, 0, 0.2)',
344 shadowBlur: 20
345 },
346 avoidLabelOverlap: false,
347 data: myData
348 }
349 ]
350 }
351 myChart.setOption(option)
352 myCharts.push(myChart)
353 }
354 async function getChart4() {
355 const result = await levelRangeCount()
356 const myData = result.data
357
358 const myChart = echarts.init(document.getElementById('chart4'))
359 const option = {
360 grid: {
361 left: '0',
362 right: '0',
363 bottom: '0',
364 top: '30',
365 containLabel: true,
366 show: true,
367 backgroundColor: '#fafbfd'
368 },
369 tooltip: {
370 trigger: 'axis'
371 },
372 color: [{
373 type: 'linear',
374 x: 0,
375 y: 0,
376 x2: 1,
377 y2: 1,
378 colorStops: [{
379 offset: 0, color: '#1DBDCD' // 0% 处的颜色
380 }, {
381 offset: 1, color: '#2CE8C7' // 100% 处的颜色
382 }],
383 global: false // 缺省为 false
384 }],
385 xAxis: { type: 'value' },
386 yAxis: {
387 type: 'category',
388 data: ['一级', '二级', '三级', '四级', '五级', '六级', '七级', '八级', '九级', '十级']
389 },
390 series: [{
391 type: 'bar',
392 itemStyle: {
393 borderWidth: 2,
394 borderColor: '#fff'
395 },
396 data: myData
397 }]
398 }
399 myChart.setOption(option)
400 myCharts.push(myChart)
401 }
402 async function getChart5() {
403 const result = await rankRangeCount()
404 const myData = result.data
405
406 const myChart = echarts.init(document.getElementById('chart5'))
407 const option = {
408 grid: {
409 left: '0',
410 right: '0',
411 bottom: '0',
412 top: '30',
413 containLabel: true,
414 show: true,
415 backgroundColor: '#fafbfd'
416 },
417 color: [{
418 type: 'linear',
419 x: 0,
420 y: 0,
421 x2: 1,
422 y2: 1,
423 colorStops: [{
424 offset: 0, color: '#3DA2DA' // 0% 处的颜色
425 }, {
426 offset: 1, color: '#4CC5F8' // 100% 处的颜色
427 }],
428 global: false // 缺省为 false
429 }],
430 tooltip: {
431 trigger: 'axis'
432 },
433 xAxis: { type: 'value' },
434 yAxis: {
435 type: 'category',
436 data: ['一段', '二段', '三段', '四段', '五段', '六段', '七段', '八段', '九段']
437 },
438 series: [{
439 type: 'bar',
440 itemStyle: {
441 borderWidth: 2,
442 borderColor: '#fff'
443 },
444 data: myData
445 }]
446 }
447 myChart.setOption(option)
448 myCharts.push(myChart)
449 }
450 async function getChart6() {
451 const result = await cityRangeCount()
452 const myData = result.data
453
454 const myChart = echarts.init(document.getElementById('chart6'))
455 const option = {
456 textStyle: {
457 color: function() {
458 return 'rgb(' + [
459 Math.round(Math.random() * 160),
460 Math.round(Math.random() * 160),
461 Math.round(Math.random() * 160)
462 ].join(',') + ')'
463 }
464 },
465 series: [{
466 type: 'wordCloud',
467 data: myData
468 }]
469 }
470 myChart.setOption(option)
471 myCharts.push(myChart)
472 }
473
474 </script>
475
476
477 <style scoped lang="scss">
478 .card{
479 background: #FFFFFF;
480 border-radius: 10px;
481 }
482 .dataItem{display: flex;align-items: center;margin:20px 5%;
483 border-right: 1px solid #eee;
484 &:last-child{border-right: none;}
485 img{width: 55px;height: 55px;margin-right: 8%;}
486 p{font-size: 15px;color: #7B7F83;margin:0 0 10px;}
487 h2{color: #2B3133;font-size: 1.8vw;margin: 0}
488 }
489 .home {
490 background: RGBA(245, 247, 249, 1);
491 font-family: "open sans", "Helvetica Neue", Helvetica, Arial, sans-serif;
492 font-size: 13px;
493 color: #676a6c;
494 overflow-x: hidden;
495 ul {
496 padding: 0;
497 margin: 0;list-style-type: none;
498 }
499 }
500 .homeTitle{font-weight: 500;color: #2B3133;margin: 30px 0 15px;}
501 .fiveflex{display: flex;justify-content: space-between;
502 .fitem{width: 18%;border-radius: 3px;display: flex;align-items: center; padding: 16px 15px;
503 p{color: #fff;}
504 img{margin-right: 20%;}
505 }
506 .wcard{width: 18%;border-radius: 10px;}
507 .ctitle{border-left:2px solid #20C59D;line-height: 1;padding-left: 10px;color: #2B3133;}
508 .cbody{display: flex;
509 p{width: 50%;
510 color: #7B7F83;}
511 span{display: block;
512 color: #2B3133;
513 font-size: 26px;}
514 }
515 .wfitem{display: flex; align-items: center;
516 img{margin-right: 20px; width: 55px;height: 55px;}
517 p{color: #7B7F83;}
518 span{display: block;font-size: 26px;color: #2B3133;}
519 }
520 }
521 .fitem:nth-child(1){background: linear-gradient(270deg, #54E1B9, #00CAA6);}
522 .fitem:nth-child(2){background: linear-gradient(270deg, #BE8EFB, #A76DF4);}
523 .fitem:nth-child(3){background: linear-gradient(90deg, #FEA449, #FFB95F);}
524 .fitem:nth-child(4){background: linear-gradient(270deg, #5E9AF3, #4169EC);}
525 .fitem:nth-child(5){background: linear-gradient(90deg, #F83841, #F76D74);}
526 .wcard{background: #fff; padding:15px;overflow: hidden;position: relative;
527 .po-title{position: absolute;
528 h3{font-size: 18px;color: #2B3133;margin: 0;}
529 h2{color: #014A9F;font-size: 30px;margin: 6px 0;}
530 p{color: #7B7F83;font-size: 18px;margin: 0;}
531 }
532 }
533 .quickbtns{
534 a{display: block;text-align: center;
535 background: #E5EDF5;
536 height: 70px;line-height: 70px;text-overflow: ellipsis;
537 overflow: hidden;white-space: nowrap;
538 font-size: 20px;margin-bottom: 20px;
539 color: #014A9F;
540 border-radius: 10px;
541 &:hover{color: #FFFFFF;background: #014A9F;}
542 }
543 }
544
545 .topflex{display: flex;justify-content: space-between;}
546 .mb40{margin-bottom: 40px;}
547
548 @media (max-width: 1400px) {
549 .quickbtns{
550 a{ font-size: 18px;}
551 }
552 .dataItem{
553 p { font-size: 14px;}
554 }
555 }
556 @media (max-width: 1200px) {
557 .quickbtns{
558 a{ font-size: 16px;}
559 }
560 }
561 </style>
562
1 <template>
2 <div class="app-container home">
3 <el-row class="card">
4 <el-col :span="4">
5 <div class="dataItem">
6 <div>
7 <p>个人会员</p>
8 <h2>{{ players }}</h2>
9 </div>
10 </div>
11
12 </el-col>
13 <el-col :span="4">
14 <div class="dataItem">
15 <div><p>团体会员</p>
16 <h2>{{ members }}</h2></div>
17 </div>
18 </el-col>
19 <el-col :span="4">
20 <div class="dataItem">
21 <div><p>教练</p>
22 <h2>{{ coach }}</h2></div>
23 </div>
24
25 </el-col>
26 <el-col :span="4">
27 <div class="dataItem">
28 <div><p>考官</p>
29 <h2>{{ examiner }}</h2></div>
30 </div>
31
32 </el-col>
33 <el-col :span="4">
34 <div class="dataItem">
35 <div><p>即将到期会员</p>
36 <h2>{{ soonGuoqiPers }}</h2></div>
37 </div>
38 </el-col>
39 <el-col :span="4">
40 <div class="dataItem">
41 <div><p>即将到期团体会员</p>
42 <h2>{{ soonGuoqiMems }}</h2></div>
43 </div>
44 </el-col>
45 </el-row>
46
47 <el-row :gutter="20">
48 <el-col :span="12">
49 <h3 class="homeTitle">操作流程</h3>
50 <el-row class="wcard quickbtns" :gutter="20">
51 <el-col :span="8" @click="router.push('/system/user')">
52 <a>用户管理</a>
53 </el-col>
54 <el-col :span="8" @click="router.push('/system/config/config')">
55 <a>参数配置</a>
56 </el-col>
57 <el-col :span="8" @click="router.push('/member/mobillize')">
58 <a>会员调动审核</a>
59 </el-col>
60 <el-col :span="8" @click="router.push('/member/audit')">
61 <a>缴费审核</a>
62 </el-col>
63 <el-col :span="8" @click="router.push('/member/feeBill')">
64 <a>缴费单记录</a>
65 </el-col>
66 <el-col :span="8" @click="router.push('/level/approval')">
67 <a>级位考试审核</a>
68 </el-col>
69 <el-col :span="8" @click="router.push('/level/cert')">
70 <a>级位考试证书发放</a>
71 </el-col>
72 <el-col :span="8" @click="router.push('/rank/approval')">
73 <a>段位考试审核</a>
74 </el-col>
75 <el-col :span="8" @click="router.push('/rank/cert')">
76 <a>段位考试证书发放</a>
77 </el-col>
78 </el-row>
79 </el-col>
80 <el-col :span="12">
81 <site-message :mes-height="270" />
82 </el-col>
83 </el-row>
84
85 <el-row :gutter="20">
86 <el-col :span="8">
87 <h3 class="homeTitle">会员年龄段分布(人数)</h3>
88 <div class="wcard">
89 <div id="chart1" style="width: 100%;height: 300px" />
90 </div>
91 </el-col>
92 <el-col :span="8">
93 <h3 class="homeTitle">会员性别分布(人数)</h3>
94 <div class="wcard">
95 <div id="chart2" style="width: 100%;height: 300px" />
96 </div>
97 </el-col>
98 <el-col :span="8">
99 <h3 class="homeTitle">各省会员数量</h3>
100 <div class="wcard">
101 <div class="po-title">
102 <!-- <h3>江苏省跆拳道协会</h3>-->
103 <!-- <h2>2300</h2>-->
104 <p>会员数</p>
105 </div>
106 <div id="chart3" style="width: 100%;height: 300px" />
107 </div>
108 </el-col>
109 <el-col :span="8">
110 <h3 class="homeTitle">会员级位分布(人数)</h3>
111 <div class="wcard">
112 <div id="chart4" style="width: 100%;height: 300px" />
113 </div>
114 </el-col>
115 <el-col :span="8">
116 <h3 class="homeTitle">会员段位分布(人数)</h3>
117 <div class="wcard">
118 <div id="chart5" style="width: 100%;height: 300px" />
119 </div>
120 </el-col>
121 <el-col :span="8">
122 <h3 class="homeTitle">会员城市分布</h3>
123 <div class="wcard">
124 <div id="chart6" style="width: 100%;height: 300px" />
125 </div>
126 </el-col>
127 </el-row>
128 </div>
129 </template>
130
131 <script setup name="Index">
132 import * as echarts from 'echarts'
133 import chinaMap from '@/assets/json/china.json'
134 import 'echarts-wordcloud'
135 import _ from 'lodash'
136 import { onMounted, onUnmounted, watch, ref } from 'vue'
137 import useAppStore from '@/store/modules/app'
138 import { useRouter } from 'vue-router'
139 import { ageRangeCount, sexRangeCount, levelRangeCount, rankRangeCount, provinceRangeCount, cityRangeCount, memberCountMap } from '@/api/system/homePage'
140 import SiteMessage from '@/views/index/components/siteMessage'
141
142
143 const router = useRouter()
144 const appStore = useAppStore()
145 const myCharts = []
146 const players = ref(0)
147 const members = ref(0)
148 const coach = ref(0)
149 const examiner = ref(0)
150 const soonGuoqiPers = ref(0)
151 const soonGuoqiMems = ref(0)
152
153 onMounted(() => {
154 getChart1()
155 getChart2()
156 getChart3()
157 getChart4()
158 getChart5()
159 getChart6()
160 getMemberCount()
161 window.onresize = _.debounce(myChartsResize, 150)
162 })
163
164 onUnmounted(() => {
165 window.onresize = null
166 _.each(myCharts, c => c.dispose())
167 })
168
169 watch(() => appStore.sidebar.opened, () => {
170 setTimeout(myChartsResize, 300)
171 })
172
173 function myChartsResize() {
174 _.each(myCharts, c => c.resize())
175 }
176
177 function getMemberCount() {
178 memberCountMap().then(res => {
179 const map = res.data
180 players.value = map.players
181 members.value = map.members
182 coach.value = map.coach
183 examiner.value = map.examiner
184 soonGuoqiPers.value = map.soonExpired
185 soonGuoqiMems.value = map.soonMember
186 })
187 }
188
189 async function getChart1() {
190 const result = await ageRangeCount()
191 const myData = result.data
192
193 const myChart = echarts.init(document.getElementById('chart1'))
194 const option = {
195 grid: {
196 left: '0',
197 right: '0',
198 bottom: '0',
199 top: '30',
200 containLabel: true,
201 show: true,
202 backgroundColor: '#fafbfd'
203 },
204 tooltip: {
205 trigger: 'axis'
206 },
207 calculable: true,
208 xAxis: [
209 {
210 type: 'category',
211 data: ['3-6 岁', '7-14 岁', '15-18 岁', '18 岁以上']
212 }
213 ],
214 yAxis: [{ type: 'value' }],
215 series: [
216 {
217 name: '会员人数',
218 type: 'pictorialBar',
219 symbol: 'roundRect',
220 symbolSize: [30, 5],
221 symbolRepeat: true,
222 symbolClip: false,
223 itemStyle: {
224 shadowColor: 'rgba(0, 0, 0, 0.3)',
225 shadowBlur: 18,
226 borderColor: '#fff',
227 borderWidth: 1,
228 color: {
229 type: 'linear',
230 x: 0,
231 y: 0,
232 x2: 0,
233 y2: 1,
234 colorStops: [{
235 offset: 0, color: '#0091ea' // 0% 处的颜色
236 }, {
237 offset: 1, color: '#36c6e1' // 100% 处的颜色
238 }],
239 globalCoord: false // 缺省为 false
240 }
241 },
242 data: myData
243 }
244 ]
245 }
246 myChart.setOption(option)
247 myCharts.push(myChart)
248 }
249 async function getChart2() {
250 // const myData = [
251 // { value: 45, name: '男' },
252 // { value: 55, name: '女' }
253 // ]
254 const result = await sexRangeCount()
255 const myData = result.data
256
257 const myChart = echarts.init(document.getElementById('chart2'))
258 const option = {
259 color: [
260 {
261 type: 'linear',
262 x: 0,
263 y: 0,
264 x2: 0,
265 y2: 1,
266 colorStops: [{
267 offset: 0, color: 'RGBA(57, 160, 221, 1)' // 0% 处的颜色
268 }, {
269 offset: 1, color: 'RGBA(61, 147, 223, 1)' // 100% 处的颜色
270 }],
271 global: false // 缺省为 false
272 }, {
273 type: 'linear',
274 x: 0,
275 y: 0,
276 x2: 0,
277 y2: 1,
278 colorStops: [{
279 offset: 0, color: 'RGBA(240, 96, 153, 1)' // 0% 处的颜色
280 }, {
281 offset: 1, color: 'RGBA(252, 101, 122, 1)' // 100% 处的颜色
282 }],
283 global: false // 缺省为 false
284 }
285 ],
286 tooltip: {
287 trigger: 'item'
288 },
289 legend: {
290 left: 'right'
291 },
292 label: {
293 formatter: '{d}%',
294 fontSize: 20,
295 fontWeight: 'bold'
296 },
297 series: [
298 {
299 type: 'pie',
300 radius: ['40%', '70%'],
301 itemStyle: {
302 borderColor: '#fff',
303 borderWidth: 2,
304 shadowColor: 'rgba(0, 0, 0, 0.2)',
305 shadowBlur: 20
306 },
307 avoidLabelOverlap: false,
308 data: myData
309 }
310 ]
311 }
312 myChart.setOption(option)
313 myCharts.push(myChart)
314 }
315 async function getChart3() {
316 // const myData = [
317 // {
318 // name: '北京市',
319 // value: 1100
320 // },
321 // {
322 // name: '上海市',
323 // value: 400
324 // },
325 // {
326 // name: '江苏省',
327 // value: 300
328 // },
329 // {
330 // name: '广东省',
331 // value: 200
332 // }
333 // ]
334 const result = await provinceRangeCount()
335 const myData = result.data
336 const myChart = echarts.init(document.getElementById('chart3'))
337 echarts.registerMap('china', chinaMap)
338 const option = {
339 tooltip: {
340 trigger: 'item',
341 // formatter: '{b}:{c}'
342 formatter: (params, ticket, callback) => {
343 return `${params.name}${params.value || 0}`
344 }
345 },
346 visualMap: {
347 type: 'continuous',
348 min: 0,
349 max: Math.max(1000, (_.maxBy(myData, item => item.value)?.value || 0)),
350 calculable: true,
351 // itemWidth: 20,
352 // itemHeight: 140,
353 text: ['高', '低'],
354 inRange: {
355 color: ['#A1D0FF', '#63B0FF', '#3D9BFF', '#158DED', '#1A7FCB']
356 }
357 },
358 series: [
359 {
360 type: 'map',
361 map: 'china',
362 roam: true,
363 zoom: 1.5,
364 top: '25%',
365 label: {
366 show: false
367 },
368 itemStyle: {
369 borderColor: '#fff'
370 },
371 emphasis: {
372 itemStyle: {
373 areaColor: '#FABD47'
374 }
375 },
376 data: myData
377 }
378 ]
379 }
380 myChart.setOption(option)
381 myCharts.push(myChart)
382 }
383 async function getChart4() {
384 // const myData = [120, 210, 150, 80, 20, 30, 40, 50, 60, 80]
385 const result = await levelRangeCount()
386 const myData = result.data
387
388 const myChart = echarts.init(document.getElementById('chart4'))
389 const option = {
390 grid: {
391 left: '0',
392 right: '0',
393 bottom: '0',
394 top: '30',
395 containLabel: true,
396 show: true,
397 backgroundColor: '#fafbfd'
398 },
399 tooltip: {
400 trigger: 'axis'
401 },
402 color: [{
403 type: 'linear',
404 x: 0,
405 y: 0,
406 x2: 1,
407 y2: 1,
408 colorStops: [{
409 offset: 0, color: '#1DBDCD' // 0% 处的颜色
410 }, {
411 offset: 1, color: '#2CE8C7' // 100% 处的颜色
412 }],
413 global: false // 缺省为 false
414 }],
415 xAxis: { type: 'value' },
416 yAxis: {
417 type: 'category',
418 data: ['一级', '二级', '三级', '四级', '五级', '六级', '七级', '八级', '九级', '十级']
419 },
420 series: [{
421 type: 'bar',
422 itemStyle: {
423 borderWidth: 2,
424 borderColor: '#fff'
425 },
426 data: myData
427 }]
428 }
429 myChart.setOption(option)
430 myCharts.push(myChart)
431 }
432 async function getChart5() {
433 // const myData = [120, 210, 150, 80, 20, 30, 40, 50, 60]
434 const result = await rankRangeCount()
435 const myData = result.data
436 const myChart = echarts.init(document.getElementById('chart5'))
437 const option = {
438 grid: {
439 left: '0',
440 right: '0',
441 bottom: '0',
442 top: '30',
443 containLabel: true,
444 show: true,
445 backgroundColor: '#fafbfd'
446 },
447 color: [{
448 type: 'linear',
449 x: 0,
450 y: 0,
451 x2: 1,
452 y2: 1,
453 colorStops: [{
454 offset: 0, color: '#3DA2DA' // 0% 处的颜色
455 }, {
456 offset: 1, color: '#4CC5F8' // 100% 处的颜色
457 }],
458 global: false // 缺省为 false
459 }],
460 tooltip: {
461 trigger: 'axis'
462 },
463 xAxis: { type: 'value' },
464 yAxis: {
465 type: 'category',
466 data: ['一段', '二段', '三段', '四段', '五段', '六段', '七段', '八段', '九段']
467 },
468 series: [{
469 type: 'bar',
470 itemStyle: {
471 borderWidth: 2,
472 borderColor: '#fff'
473 },
474 data: myData
475 }]
476 }
477 myChart.setOption(option)
478 myCharts.push(myChart)
479 }
480 async function getChart6() {
481 // const myData = [
482 // {
483 // name: '北京市',
484 // value: 1100
485 // },
486 // {
487 // name: '上海市',
488 // value: 400
489 // },
490 // {
491 // name: '江苏省',
492 // value: 300
493 // },
494 // {
495 // name: '广东省',
496 // value: 2000
497 // }
498 // ]
499 const result = await cityRangeCount()
500 const myData = result.data
501
502 const myChart = echarts.init(document.getElementById('chart6'))
503 const option = {
504 textStyle: {
505 color: function() {
506 return 'rgb(' + [
507 Math.round(Math.random() * 160),
508 Math.round(Math.random() * 160),
509 Math.round(Math.random() * 160)
510 ].join(',') + ')'
511 }
512 },
513 series: [{
514 type: 'wordCloud',
515 data: myData
516 }]
517 }
518 myChart.setOption(option)
519 myCharts.push(myChart)
520 }
521
522 </script>
523
524
525 <style scoped lang="scss">
526 .card{
527 background: #FFFFFF;
528 border-radius: 10px;
529 }
530 .dataItem{display: flex;align-items: center;margin:20px 5%;
531 border-right: 1px solid #eee;
532 &:last-child{border-right: none;}
533 img{width: 55px;height: 55px;margin-right: 8%;}
534 p{font-size: 15px;color: #7B7F83;margin:0 0 10px;}
535 h2{color: #2B3133;font-size: 1.8vw;margin: 0}
536 }
537 .home {
538 background: RGBA(245, 247, 249, 1);
539 font-family: "open sans", "Helvetica Neue", Helvetica, Arial, sans-serif;
540 font-size: 13px;
541 color: #676a6c;
542 overflow-x: hidden;
543 ul {
544 padding: 0;
545 margin: 0;list-style-type: none;
546 }
547 }
548 .homeTitle{font-weight: 500;color: #2B3133;margin: 30px 0 15px;}
549 .fiveflex{display: flex;justify-content: space-between;
550 .fitem{width: 18%;border-radius: 3px;display: flex;align-items: center; padding: 16px 15px;
551 p{color: #fff;}
552 img{margin-right: 20%;}
553 }
554 .wcard{width: 18%;border-radius: 10px;}
555 .ctitle{border-left:2px solid #20C59D;line-height: 1;padding-left: 10px;color: #2B3133;}
556 .cbody{display: flex;
557 p{width: 50%;
558 color: #7B7F83;}
559 span{display: block;
560 color: #2B3133;
561 font-size: 26px;}
562 }
563 .wfitem{display: flex; align-items: center;
564 img{margin-right: 20px; width: 55px;height: 55px;}
565 p{color: #7B7F83;}
566 span{display: block;font-size: 26px;color: #2B3133;}
567 }
568 }
569 .fitem:nth-child(1){background: linear-gradient(270deg, #54E1B9, #00CAA6);}
570 .fitem:nth-child(2){background: linear-gradient(270deg, #BE8EFB, #A76DF4);}
571 .fitem:nth-child(3){background: linear-gradient(90deg, #FEA449, #FFB95F);}
572 .fitem:nth-child(4){background: linear-gradient(270deg, #5E9AF3, #4169EC);}
573 .fitem:nth-child(5){background: linear-gradient(90deg, #F83841, #F76D74);}
574 .wcard{background: #fff; padding:15px;overflow: hidden;position: relative;
575 .po-title{position: absolute;
576 h3{font-size: 18px;color: #2B3133;margin: 0;}
577 h2{color: #014A9F;font-size: 30px;margin: 6px 0;}
578 p{color: #7B7F83;font-size: 18px;margin: 0;}
579 }
580 }
581 .quickbtns{
582 a{display: block;text-align: center;
583 background: #E5EDF5;
584 height: 70px;line-height: 70px;text-overflow: ellipsis;
585 overflow: hidden;white-space: nowrap;
586 font-size: 20px;margin-bottom: 20px;
587 color: #014A9F;
588 border-radius: 10px;
589 &:hover{color: #FFFFFF;background: #014A9F;}
590 }
591 }
592
593 .mesUl{
594 height: 270px; overflow: auto;
595 li{ position: relative;line-height: 45px;padding-left: 40px;
596 font-size: 16px;text-overflow: ellipsis;overflow: hidden;white-space: nowrap;
597 color: #666;cursor: pointer;
598 &:before{width: 6px;content: '';
599 height: 6px;position: absolute;left: 20px;top: 0;bottom: 0;margin: auto;
600 background: var(--el-color-primary);
601 border-radius: 50%;}
602 &:hover{background: #f4f4f4;}
603 .link{display: inline-block;}
604 }
605 }
606 .topflex{display: flex;justify-content: space-between;}
607 .mb40{margin-bottom: 40px;}
608
609 @media (max-width: 1400px) {
610 .quickbtns{
611 a{ font-size: 18px;}
612 }
613 .dataItem{
614 p { font-size: 14px;}
615 }
616 }
617 @media (max-width: 1200px) {
618 .quickbtns{
619 a{ font-size: 16px;}
620 }
621 }
622 </style>
623
1 <template>
2 <div class="app-container">
3 <div class="box">
4 <el-row :gutter="20">
5 <el-col :lg="5" :md="5" :xl="6" :sm="8" :xs="8">
6 <el-card class="mb20">
7 <div :class="language==0?'center-menu':'center-menu en-menu'">
8 <ul v-if="user.utype=='2'&&language==0">
9 <li v-for="(m, i) in menus"
10 :key="i"
11 :class="{ active: m.isActive }"
12 >
13 <a href="javascript:void(0)" @click="toInfo(m,menus)">
14 <img :src="m.isActive ? m.picUrl2 : m.picUrl1">
15 {{m.name }}
16 </a>
17 </li>
18 </ul>
19 <ul v-if="user.utype=='2'&&language==1">
20 <li v-for="(m, i) in menusEn"
21 :key="i"
22 :class="{ active: m.isActive }"
23 >
24 <a href="javascript:void(0)" @click="toInfo(m,menusEn)">
25 <img :src="m.isActive ? m.picUrl2 : m.picUrl1">
26 {{m.name }}
27 </a>
28 </li>
29 </ul>
30 <ul v-if="user.utype=='1'&&language==0">
31 <li
32 v-for="(m, i) in menusPersonal"
33 :key="i"
34 :class="{ active: m.isActive }"
35 >
36 <a href="javascript:void(0)" @click="toInfo(m,menusPersonal)">
37 <img :src="m.isActive ? m.picUrl2 : m.picUrl1">
38 {{ m.name }}
39 </a>
40 </li>
41 </ul>
42 <ul v-if="user.utype=='1'&&language==1">
43 <li
44 v-for="(m, i) in menusPersonalEn"
45 :key="i"
46 :class="{ active: m.isActive }"
47 >
48 <a href="javascript:void(0)" @click="toInfo(m,menusPersonalEn)">
49 <img :src="m.isActive ? m.picUrl2 : m.picUrl1">
50 {{ m.name }}
51 </a>
52 </li>
53 </ul>
54 <ul v-if="user.utype=='3'&&language==0">
55 <li
56 v-for="(m, i) in menus3"
57 :key="i"
58 :class="{ active: m.isActive }"
59 >
60 <a href="javascript:void(0)" @click="toInfo(m,menus3)">
61 <img :src="m.isActive ? m.picUrl2 : m.picUrl1">
62 {{ m.name }}
63 </a>
64 </li>
65 </ul>
66 <ul v-if="user.utype=='3'&&language==1">
67 <li
68 v-for="(m, i) in menus3En"
69 :key="i"
70 :class="{ active: m.isActive }"
71 >
72 <a href="javascript:void(0)" @click="toInfo(m,menus3En)">
73 <img :src="m.isActive ? m.picUrl2 : m.picUrl1">
74 {{ m.name }}
75 </a>
76 </li>
77 </ul>
78 </div>
79 </el-card>
80 </el-col>
81 <el-col :lg="19" :md="19" :xl="18" :sm="16" :xs="16">
82 <router-view :user="user" class="rightPart"/>
83 </el-col>
84 </el-row>
85 </div>
86 </div>
87 </template>
88
89 <script setup>
90 import {ref} from 'vue'
91 import {useRoute, useRouter} from 'vue-router'
92 import {onMounted} from '@vue/runtime-core'
93 import useUserStore from '@/store/modules/user'
94 import _ from 'lodash'
95 import {useStorage} from "@vueuse/core/index";
96 const language= useStorage('language',0)
97
98 const route = useRoute()
99 const router = useRouter()
100
101 const user = useUserStore().user || {}
102 const menus = ref([
103 {
104 name: language.value==0?'基础信息':'Basic Information',
105 routeName: 'myInfo',
106 picUrl1: '/img/nav_26.png',
107 picUrl2: '/img/nav_26_dwn.png',
108 isActive: false
109 },
110 {
111 name: language.value==0?'修改密码':'Change Password',
112 routeName: 'myPassword',
113 picUrl1: '/img/nav_27.png',
114 picUrl2: '/img/nav_27_dwn.png',
115 isActive: false
116 },
117 {
118 name: language.value==0?'团队认证':'Organization Recognition',
119 routeName: 'myCertification',
120 picUrl1: '/img/nav_32.png',
121 picUrl2: '/img/nav_32_dwn.png',
122 isActive: false
123 },
124 {
125 name: language.value==0?'选手管理':'Athlete Management',
126 routeName: 'myMember',
127 picUrl1: '/img/nav_31.png',
128 picUrl2: '/img/nav_31_dwn.png',
129 isActive: false
130 },
131 {
132 name: language.value==0?'我的报名':'My Registration',
133 routeName: 'myMatch',
134 picUrl1: '/img/nav_28.png',
135 picUrl2: '/img/nav_28_dwn.png',
136 isActive: false
137 },
138 {
139 name: language.value==0?'我的预订':'My Reservation',
140 routeName: 'myReservation',
141 picUrl1: '/img/nav_29.png',
142 picUrl2: '/img/nav_29_dwn.png',
143 isActive: false
144 },
145 {
146 name: language.value==0?'票务预订':'Ticket Reservation',
147 routeName: 'seat_order',
148 picUrl1: '/img/c7.png',
149 picUrl2: '/img/c7.png',
150 isActive: false
151 },
152 {
153 name: language.value==0?'系统消息':'System messages',
154 routeName: 'mySms',
155 picUrl1: '/img/nav_30.png',
156 picUrl2: '/img/nav_30_dwn.png',
157 isActive: false
158 },
159 {
160 name: language.value==0?'发票申请':'Electronic invoice',
161 routeName: 'myKP',
162 picUrl1: '/img/fp.svg',
163 picUrl2: '/img/fp_dwn.svg',
164 isActive: false
165 }
166 ])
167 const menusEn = ref([
168 {
169 name: language.value==0?'基础信息':'Basic Information',
170 routeName: 'myInfo',
171 picUrl1: '/img/nav_26.png',
172 picUrl2: '/img/nav_26_dwn.png',
173 isActive: false
174 },
175 {
176 name: language.value==0?'修改密码':'Change Password',
177 routeName: 'myPassword',
178 picUrl1: '/img/nav_27.png',
179 picUrl2: '/img/nav_27_dwn.png',
180 isActive: false
181 },
182 {
183 name: language.value==0?'团队认证':'Organization Recognition',
184 routeName: 'myCertification',
185 picUrl1: '/img/nav_32.png',
186 picUrl2: '/img/nav_32_dwn.png',
187 isActive: false
188 },
189 {
190 name: language.value==0?'选手管理':'Athlete Management',
191 routeName: 'myMember',
192 picUrl1: '/img/nav_31.png',
193 picUrl2: '/img/nav_31_dwn.png',
194 isActive: false
195 },
196 {
197 name: language.value==0?'我的报名':'My Registration',
198 routeName: 'myMatch',
199 picUrl1: '/img/nav_28.png',
200 picUrl2: '/img/nav_28_dwn.png',
201 isActive: false
202 },
203 {
204 name: language.value==0?'我的预订':'My Reservation',
205 routeName: 'myReservation',
206 picUrl1: '/img/nav_29.png',
207 picUrl2: '/img/nav_29_dwn.png',
208 isActive: false
209 },
210 {
211 name: language.value==0?'票务预订':'Ticket Reservation',
212 routeName: 'seat_order',
213 picUrl1: '/img/c7.png',
214 picUrl2: '/img/c7.png',
215 isActive: false
216 },
217 {
218 name: language.value==0?'系统消息':'System messages',
219 routeName: 'mySms',
220 picUrl1: '/img/nav_30.png',
221 picUrl2: '/img/nav_30_dwn.png',
222 isActive: false
223 }
224 ])
225 const menus3 = ref([
226 {
227 name: language.value==0?'基础信息':'Basic Information',
228 routeName: 'myInfo',
229 picUrl1: '/img/nav_26.png',
230 picUrl2: '/img/nav_26_dwn.png',
231 isActive: false
232 },
233 {
234 name: language.value==0?'修改密码':'Change Password',
235 routeName: 'myPassword',
236 picUrl1: '/img/nav_27.png',
237 picUrl2: '/img/nav_27_dwn.png',
238 isActive: false
239 },
240 {
241 name: language.value==0?'我的预订':'My Reservation',
242 routeName: 'myReservation',
243 picUrl1: '/img/nav_29.png',
244 picUrl2: '/img/nav_29_dwn.png',
245 isActive: false
246 },
247 {
248 name: language.value==0?'票务预订':'Ticket Reservation',
249 routeName: 'seat_order',
250 picUrl1: '/img/c7.png',
251 picUrl2: '/img/c7.png',
252 isActive: false
253 },
254 {
255 name: language.value==0?'发票申请':'Electronic invoice',
256 routeName: 'myKP',
257 picUrl1: '/img/fp.svg',
258 picUrl2: '/img/fp_dwn.svg',
259 isActive: false
260 }
261 ])
262 const menus3En = ref([
263 {
264 name: language.value==0?'基础信息':'Basic Information',
265 routeName: 'myInfo',
266 picUrl1: '/img/nav_26.png',
267 picUrl2: '/img/nav_26_dwn.png',
268 isActive: false
269 },
270 {
271 name: language.value==0?'修改密码':'Change Password',
272 routeName: 'myPassword',
273 picUrl1: '/img/nav_27.png',
274 picUrl2: '/img/nav_27_dwn.png',
275 isActive: false
276 },
277 {
278 name: language.value==0?'我的预订':'My Reservation',
279 routeName: 'myReservation',
280 picUrl1: '/img/nav_29.png',
281 picUrl2: '/img/nav_29_dwn.png',
282 isActive: false
283 },
284 {
285 name: language.value==0?'票务预订':'Ticket Reservation',
286 routeName: 'seat_order',
287 picUrl1: '/img/c7.png',
288 picUrl2: '/img/c7.png',
289 isActive: false
290 }
291 ])
292 const menusPersonal = ref([
293 {
294 name: language.value==0?'基础信息':'Basic Information',
295 routeName: 'myInfo',
296 picUrl1: '/img/nav_26.png',
297 picUrl2: '/img/nav_26_dwn.png',
298 isActive: false
299 },
300 {
301 name: language.value==0?'修改密码':'Change Password',
302 routeName: 'myPassword',
303 picUrl1: '/img/nav_27.png',
304 picUrl2: '/img/nav_27_dwn.png',
305 isActive: false
306 },
307 {
308 name: language.value==0?'我的报名':'My Registration',
309 routeName: 'myMatch',
310 picUrl1: '/img/nav_28.png',
311 picUrl2: '/img/nav_28_dwn.png',
312 isActive: false
313 },
314 {
315 name: language.value==0?'我的预订':'My Reservation',
316 routeName: 'myReservation',
317 picUrl1: '/img/nav_29.png',
318 picUrl2: '/img/nav_29_dwn.png',
319 isActive: false
320 },
321 {
322 name: language.value==0?'票务预订':'Ticket Reservation',
323 routeName: 'seat_order',
324 picUrl1: '/img/c7.png',
325 picUrl2: '/img/c7.png',
326 isActive: false
327 },
328 {
329 name: language.value==0?'系统消息':'System messages',
330 routeName: 'mySms',
331 picUrl1: '/img/nav_30.png',
332 picUrl2: '/img/nav_30_dwn.png',
333 isActive: false
334 },
335 {
336 name: language.value==0?'发票申请':'Electronic invoice',
337 routeName: 'myKP',
338 picUrl1: '/img/fp.svg',
339 picUrl2: '/img/fp_dwn.svg',
340 isActive: false
341 }
342 ])
343 const menusPersonalEn = ref([
344 {
345 name: language.value==0?'基础信息':'Basic Information',
346 routeName: 'myInfo',
347 picUrl1: '/img/nav_26.png',
348 picUrl2: '/img/nav_26_dwn.png',
349 isActive: false
350 },
351 {
352 name: language.value==0?'修改密码':'Change Password',
353 routeName: 'myPassword',
354 picUrl1: '/img/nav_27.png',
355 picUrl2: '/img/nav_27_dwn.png',
356 isActive: false
357 },
358 {
359 name: language.value==0?'我的报名':'My Registration',
360 routeName: 'myMatch',
361 picUrl1: '/img/nav_28.png',
362 picUrl2: '/img/nav_28_dwn.png',
363 isActive: false
364 },
365 {
366 name: language.value==0?'我的预订':'My Reservation',
367 routeName: 'myReservation',
368 picUrl1: '/img/nav_29.png',
369 picUrl2: '/img/nav_29_dwn.png',
370 isActive: false
371 },
372 {
373 name: language.value==0?'票务预订':'Ticket Reservation',
374 routeName: 'seat_order',
375 picUrl1: '/img/c7.png',
376 picUrl2: '/img/c7.png',
377 isActive: false
378 },
379 {
380 name: language.value==0?'系统消息':'System messages',
381 routeName: 'mySms',
382 picUrl1: '/img/nav_30.png',
383 picUrl2: '/img/nav_30_dwn.png',
384 isActive: false
385 }
386 ])
387 let currMenu
388 onMounted(() => {
389 console.log(route.query)
390 if(!user.utype){
391 router.push({name: 'home'})
392 return
393 }
394 if(user.utype=='1'){
395 currMenu = _.find(menusPersonal.value, (m) => {
396 return m.routeName === route.name
397 })
398 currMenu.isActive = true
399 }
400 console.log(route.name)
401
402 if(user.utype=='2'){
403 currMenu = _.find(menus.value, (m) => {
404 return m.routeName === route.name
405 })
406 currMenu.isActive = true
407 }
408 if(user.utype=='3'){
409 currMenu = _.find(menus3.value, (m) => {
410 return m.routeName === route.name
411 })
412 currMenu.isActive = true
413 }
414
415 })
416
417 const toInfo = (item,list) => {
418 _.each(list, (m) => {
419 m.isActive = false
420 })
421 item.isActive = true
422
423 router.push({
424 name: item.routeName
425 })
426 }
427 </script>
428
429 <style scoped lang="scss">
430 :deep(.el-tabs__nav-wrap) {
431 padding: 0 15px;
432 }
433
434 .center-menu {
435 text-align: center;
436
437 li {
438 margin-bottom: 15px;
439 }
440 &.en-menu{text-align: left;
441 li{padding: 6px 0 6px 14px;
442 a{display: flex;align-items: center;}
443 }
444 img{padding: 0;width: 26px;}
445 }
446 }
447
448 li img {
449 display: inline-block;
450 vertical-align: middle;
451 margin-right: 10px;
452 padding: 5px;
453 }
454
455 .active {
456 color: #fff;
457 background: linear-gradient(90deg, #8623FC, #453DEA);
458 border-radius: 20px;
459 }
460 @media (max-width: 500px) {
461 .pd20{padding: 8px;}
462 .el-card{box-shadow: none!important;
463 :deep(.el-card__body){padding: 0!important;}
464 }
465 .el-col{padding: 0!important;}
466 .center-menu{height: 100vh;padding: 20px 0;position: fixed;left: 0;z-index: 1;
467 background: #F5F7F9;top: 80px;width: 100px;border-right: 1px solid #eee;
468 li{font-size: 13px;padding:8px 10px;border-radius: 0;
469 img{display: none}
470 &.active{background: #fff;
471 border-left: 2px solid var(--el-color-primary);
472 color: var(--el-color-primary);}
473 }
474 }
475 .rightPart{width: calc(100vw - 100px);left: 100px;position: fixed; z-index: 1;
476 height: calc(100vh - 80px);overflow: auto;top: 80px;background: #fff;
477 }
478 }
479 .app-container{min-height: 80vh;}
480 </style>
1 <template>
2 <div class="mb20">
3 <el-card :body-style="{'padding':'0'}">
4 <div class="indexTitle">
5 <h3 class="leftboderTT" v-if="user.utype=='2'">
6 {{ language == 0 ? '机构基础信息' : 'ORGANIZATION BASIC INFORMATION' }}</h3>
7 <h3 class="leftboderTT" v-if="user.utype=='1'">{{
8 language == 0 ? '个人基础信息' : 'Personal Basic Information'
9 }}</h3>
10 </div>
11 <!-- uType字段 1 是个人 2是团体-->
12 <!-- {{user}}-->
13 <team-info :form="myform" v-if="user.utype=='2'"/>
14 <div class="pd20" v-else>
15 <div class="d-form-border" style="margin-top: 0">
16 <el-form class="d-form" label-width="120" :rules="rules" ref="formref"
17 :label-position="language==0?'left':'top'" style="max-width: 500px;margin: auto">
18 <el-form-item :label="language==0?'用户名':'Account'">
19 {{ user.userName }}
20 </el-form-item>
21 <el-form-item :label="language==0?'姓名':'Real Name'" required prop="realName" v-if="user.utype=='1'">
22 <el-input v-model="myform.realName" disabled/>
23 </el-form-item>
24 <el-form-item :label="language==0?'性别':'Gender'" required >
25 <el-radio-group v-model="myform.sex">
26 <el-radio value="0">{{ language == 0 ? '女' : 'female' }}</el-radio>
27 <el-radio value="1">{{ language == 0 ? '男' : 'male' }}</el-radio>
28 </el-radio-group>
29 </el-form-item>
30 <el-form-item :label="language==0?'出生日期':'Date of Birth'">
31 <el-date-picker
32 v-model="myform.birth"
33 style="width: 100%;"
34 type="date" format="YYYY-MM-DD" value-format="YYYY-MM-DD"
35 />
36 </el-form-item>
37 <el-form-item :label="language==0?'代表':'Representing'" required v-if="user.utype=='1'">
38 <el-input v-model="myform.representing" disabled/>
39 </el-form-item>
40 <el-form-item :label="language==1?'Age group':'年龄组'" required v-if="user.utype=='1'">
41 <el-input v-model="myform.ageGroup" disabled/>
42 </el-form-item>
43 <el-form-item :label="language==0?'舞种':'Division'" required v-if="user.utype=='1'">
44 <el-input v-model="myform.division" disabled/>
45 </el-form-item>
46 <el-form-item :label="language==0?'状态':'Status'" required v-if="user.utype=='1'">
47 <el-input v-model="myform.wdsfStatus" disabled/>
48 </el-form-item>
49 <el-form-item :label="language==0?'证件号':'Passport number'" required v-if="user.utype=='1'">
50 <el-input v-model="myform.passportNumber" disabled/>
51 </el-form-item>
52 <el-form-item :label="language==0?'有效证件':'Valid Passport'" required v-if="user.utype=='1'">
53 <image-upload v-model="myform.passportUrl" :limit="1" :is-show-tip="false"
54 :button-text="language==0?'上传':'Upload'"/>
55 </el-form-item>
56 <el-form-item :label="language==0?'WDSF会员号':'WDSF MIN'" prop="wdsfMin" v-if="user.utype=='1'">
57 {{myform.wdsfMin}}
58 </el-form-item>
59 <!-- <el-form-item :label="language==0?'证件类型':'ID type'" required prop="idcType">-->
60 <!-- <el-select v-model="myform.idcType" style="width: 100%">-->
61 <!-- <el-option-->
62 <!-- v-for="item in certificates"-->
63 <!-- :key="item.value"-->
64 <!-- :label="item.label"-->
65 <!-- :value="item.value"-->
66 <!-- />-->
67 <!-- </el-select>-->
68 <!-- </el-form-item>-->
69 <!-- <el-form-item :label="language==0?'证件号码':'ID NO'" prop="idcCode">-->
70 <!-- <el-input v-model="myform.idcCode" @blur="checkCode"/>-->
71 <!-- </el-form-item>-->
72 <!-- <el-form-item :label="language==0?'类型':'Type'" required>-->
73 <!-- <el-select v-model="myform.type" style="width: 100%;">-->
74 <!-- <el-option :label="language==0?'业余':'amateur'" value="0"/>-->
75 <!-- <el-option :label="language==0?'专业':'Professional'" value="1"/>-->
76 <!-- <el-option :label="language==0?'大专院校':'Colleges and universities'" value="2"/>-->
77 <!-- <el-option :label="language==0?'其他':'Other'" value="3"/>-->
78 <!-- </el-select>-->
79 <!-- </el-form-item>-->
80 <!-- <el-form-item :label="language==0?'邮箱':'Email'" required prop="email">-->
81 <!-- <el-input v-model="myform.email" type="email" :placeholder="language==0?'请输入内容':''"/>-->
82 <!-- </el-form-item>-->
83 </el-form>
84 <div class="text-center" v-if="user.utype=='1'||user.utype=='2'">
85 <el-button type="primary" class="btn-lineG" round @click="save">
86 {{language == 0 ? '确定修改' : 'Save'}}
87 </el-button>
88 </div>
89
90 </div>
91 </div>
92 </el-card>
93
94 </div>
95 </template>
96
97 <script setup>
98 import {ref} from 'vue'
99 import {useRouter} from 'vue-router'
100 import {getCurrentInstance, onMounted} from '@vue/runtime-core'
101 import * as match from '@/apiPc/match'
102 import {ElMessage, ElMessageBox} from 'element-plus'
103 import useUserStore from "@/store/modules/user";
104 import {useStorage} from "@vueuse/core/index";
105
106 const language= useStorage('language',0)
107 const router = useRouter()
108 const {proxy} = getCurrentInstance()
109 const props = defineProps({
110 user: {
111 type: Object,
112 required: true
113 }
114 })
115 const rules = ref({
116 realName: [{required: true, message: '必填', trigger: 'blur'}],
117 sex: [{required: true, message: '必填', trigger: 'change'}],
118 idcType: [{required: true, message: '必填', trigger: 'change'}],
119 type: [{required: true, message: '必填', trigger: 'change'}],
120 idcCode: [{required: true, message: '必填', trigger: 'blur'}],
121 email: [{required: true, message: '必填', trigger: 'blur'}],
122
123 })
124 const activeName = ref('first')
125 const myform = ref({
126 idcType: 0,
127 countryId: '',
128 realName: ''
129 })
130 const labelArr = ref([])
131
132 const certificates = ref([
133 {
134 value: '0',
135 label: language.value == 0 ? '居民身份证' : 'Resident ID card'
136 },
137 {
138 value: '1',
139 label: language.value == 0 ? '护照' : 'Passport'
140 },
141 {
142 value: '2',
143 label: language.value == 0 ? '其他' : 'Other'
144 }
145 ])
146 const user = useUserStore().user || {}
147 getData()
148
149 function getData() {
150 if (user.utype == '2') {
151 match.getGroupInfo().then(res => {
152 myform.value = res.data
153 })
154 }
155 if (user.utype == '1') {
156 match.getMyPersonInfo().then(res => {
157 myform.value = res.data
158 if(language.value=='1'){
159 myform.value.type = '1'
160 }
161 })
162 }
163
164 }
165
166 function save() {
167 match.saveMyBaseInfo(myform.value).then(res => {
168 ElMessage.success(language.value==0?'保存成功':'Save successfully')
169 })
170 }
171
172 function checkCode() {
173 if (myform.value.idcType == 0 && myform.value.idcCode) {
174 if (!(/(^\d{15}$)|(^\d{17}([0-9]|X)$)/.test(myform.value.idcCode))) {
175 ElMessage.warning('请输入正确的身份证号码')
176 } else {
177 let tmpStr = ''
178 if (myform.value.idcCode.length == 15) {
179 tmpStr = myform.value.idcCode.substring(6, 12)
180 tmpStr = '19' + tmpStr
181 tmpStr = tmpStr.substring(0, 4) + '-' + tmpStr.substring(4, 6) + '-' + tmpStr.substring(6)
182 } else {
183 tmpStr = myform.value.idcCode.substring(6, 14)
184 tmpStr = tmpStr.substring(0, 4) + '-' + tmpStr.substring(4, 6) + '-' + tmpStr.substring(6)
185 }
186 myform.value.birth = tmpStr
187
188 const res = /^(\d{6})(\d{4})(\d{2})(\d{2})(\d{3})([0-9]|X)$/
189 if (myform.value.idcCode && res.test(myform.value.idcCode)) {
190 const genderCode = myform.value.idcCode.charAt(16)
191 if (parseInt(genderCode) % 2 == 0) {
192 myform.value.sex = '0'
193 } else {
194 myform.value.sex = '1'
195 }
196 }
197 }
198 }
199 }
200
201
202 </script>
203
204 <style scoped lang="scss">
205 .indexTitle {
206 margin: 20px 0 12px;
207 padding: 0 20px 15px;
208 border-bottom: 1px solid #e5e5e5;
209
210 h3 {
211 font-size: 16px;
212 color: var(--el-color-primary);
213 }
214 }
215
216
217 </style>
1 <template>
2 <div class="mb20">
3 <el-card :body-style="{'padding':'0'}">
4 <div class="indexTitle"><h3 class="leftboderTT">{{ language==0?'修改密码':'Change Password' }}</h3></div>
5
6 <div class="pd20">
7 <div class="d-form-border" style="margin-top: 0">
8 <el-form class="d-form" ref="pwdRef" :model="user" :rules="rules"
9 label-width="120px" :label-position="language==0?'left':'top'"
10 style="max-width: 500px;margin: auto">
11 <el-form-item :label="language==0?'旧密码':'Old Password'" prop="oldPassword">
12 <el-input v-model="user.oldPassword" :placeholder="language==0?'请输入旧密码':''" type="password" show-password/>
13 </el-form-item>
14 <el-form-item :label="language==0?'新密码':'New Password'" prop="newPassword">
15 <el-input v-model="user.newPassword" :placeholder="language==0?'请设置8位以上大小写字母、数字、特殊符号':''" type="password"
16 show-password/>
17 </el-form-item>
18 <el-form-item :label="language==0?'确认密码':'Confirm Password'" prop="confirmPassword">
19 <el-input v-model="user.confirmPassword" :placeholder="language==0?'请确认新密码':''" type="password" show-password/>
20 </el-form-item>
21
22 </el-form>
23 </div>
24 <el-row justify="center">
25 <el-button type="primary" class="btn-lineG" round @click="submit">{{ language==0?'保存':'Save' }}</el-button>
26 </el-row>
27 </div>
28 </el-card>
29 </div>
30 </template>
31
32 <script setup>
33 import {updateUserPwd} from '@/api/system/user'
34 import useUserStore from '@/store/modules/user'
35 import {reactive, ref, getCurrentInstance} from 'vue'
36 import {validPassword} from '@/utils/validate'
37 import {useStorage} from "@vueuse/core/index";
38 const language = useStorage('language', 0)
39
40 const show = ref(false)
41 const {proxy} = getCurrentInstance()
42 const userStore = useUserStore()
43
44 const user = reactive({
45 oldPassword: undefined,
46 newPassword: undefined,
47 confirmPassword: undefined
48 })
49
50 const equalToPassword = (rule, value, callback) => {
51 if (user.newPassword !== value) {
52 callback(new Error('两次输入的密码不一致'))
53 } else {
54 callback()
55 }
56 }
57
58 const validPwd = (rule, value, callback) => {
59 if (import.meta.env.DEV) {
60 callback()
61 } else {
62 if (!validPassword(value)) {
63 callback(new Error('请设置8位以上大小写字母、数字、特殊符号组合的密码'))
64 } else {
65 callback()
66 }
67 }
68 }
69
70 const rules = ref({
71 oldPassword: [{required: true, message: language.value==0?'旧密码不能为空':'required', trigger: 'blur'}],
72 newPassword: [
73 {required: true, message: language.value==0?'新密码不能为空':'required', trigger: 'blur'},
74 {validator: validPwd, trigger: 'blur'}
75 ],
76 confirmPassword: [
77 {required: true, message: language.value==0?'确认密码不能为空':'required', trigger: 'blur'},
78 {required: true, validator: equalToPassword, trigger: 'blur'}
79 ]
80 })
81
82 /** 提交按钮 */
83 function submit() {
84 proxy.$refs['pwdRef'].validate(valid => {
85 if (valid) {
86 updateUserPwd(user.oldPassword, user.newPassword).then(response => {
87 proxy.$modal.msgSuccess(language.value==0?'修改成功':'password is changed!')
88
89 userStore.logOut().then(() => {
90 setTimeout(() => {
91 location.reload()
92 }, 1000)
93 })
94 })
95 }
96 })
97 }
98
99 </script>
100
101 <style scoped lang="scss">
102 .indexTitle {
103 margin: 20px 0 12px;
104 padding: 0 20px 15px;
105 border-bottom: 1px solid #e5e5e5;
106
107 h3 {
108 font-size: 16px;
109 color: var(--el-color-primary);
110 }
111 }
112
113
114 </style>
...@@ -2,8 +2,6 @@ ...@@ -2,8 +2,6 @@
2 2
3 <!-- --> 3 <!-- -->
4 <div class="partA"> 4 <div class="partA">
5 <rotate-part>
6 </rotate-part>
7 5
8 <div class="gif_bg"> 6 <div class="gif_bg">
9 <img src="@/assets/img/rote.png"> 7 <img src="@/assets/img/rote.png">
...@@ -93,7 +91,6 @@ ...@@ -93,7 +91,6 @@
93 </template> 91 </template>
94 92
95 <script setup> 93 <script setup>
96 import rotatePart from './rotatePart'
97 import {onMounted, ref, watch} from 'vue' 94 import {onMounted, ref, watch} from 'vue'
98 import {ArrowRight} from '@element-plus/icons-vue' 95 import {ArrowRight} from '@element-plus/icons-vue'
99 import {szToHz} from '@/utils/ruoyi' 96 import {szToHz} from '@/utils/ruoyi'
......
1 <template>
2
3 <div class="ellipse">
4 <div :class="`circle circle${i+1}`" v-for="(n,i) in list">
5 <div class="ma">
6 <!-- <img v-if="i >= 0 && i < 5" :class="`iconImg`" :src="getBtnImagePath(i)">-->
7 <img v-if="i==0" class="iconImg" src="@/assets/img/btn01.png">
8 <img v-if="i==1" class="iconImg" src="@/assets/img/btn02.png">
9 <img v-if="i==2" class="iconImg" src="@/assets/img/btn03.png">
10 <img v-if="i==3" class="iconImg" src="@/assets/img/btn04.png">
11 <img v-if="i==4" class="iconImg" src="@/assets/img/btn05.png">
12 <div class="statistic">
13 <h3>{{n.name}}</h3>
14 <p v-if="Array.isArray(n.num)">
15 {{Number(n.num[0]/10000).toFixed(2)}} 万卷/<br/>
16 {{Number(n.num[1]/10000).toFixed(2)}} 万件
17 </p>
18 <p v-else>{{n.num}}</p>
19 </div>
20
21 <!-- <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>-->
22 </div>
23 </div>
24 </div>
25
26 </template>
27
28 <script setup>
29 import {onMounted, ref} from "vue";
30 import {Swiper, SwiperSlide} from 'swiper/vue'
31 import {Autoplay, Navigation} from 'swiper'
32 import * as api from "@/apiPc/common"
33 const statisticStyle = ref({'color':'#fff'})
34 const modules = ref([Autoplay])
35 const list =ref([])
36 let intervalA = null
37 onMounted(()=>{
38 init()
39 })
40
41 function init() {
42 if(!intervalA){
43 getdata()
44 }
45 intervalA = setInterval(getdata, 1000*60*60);
46 }
47 const getdata = () => {
48 api.getBasicInfo().then(res=>{
49 list.value = []
50 let arr = res.data
51 for (let n in arr){
52 let obj = {name:n,num:arr[n]}
53 list.value.push(obj)
54 }
55 })
56 }
57 function getBtnImagePath(index) {
58 return require(`@/assets/img/btn${index + 1}.png`);
59 }
60 //动画的暂停与开始
61 var svg1 = document.getElementById("svg_an");
62 function pauseAn() {
63 svg1.pauseAnimations();
64 }
65 function unpauseAn() {
66 svg1.unpauseAnimations();
67 }
68
69 </script>
70
71 <style scoped lang="scss">
72 /* 定义旋转动画 */
73 @keyframes rotate {
74 0%{
75 transform: rotate3d(1,1,1,0deg);
76 }
77 100%{
78 transform: rotate3d(1,1,1,360deg);
79 }
80 }
81 :deep(.el-statistic__head){
82 font-family: 'YouSheBiaoTiHei';
83 background: linear-gradient(180deg, #fff 10%, #9CD2FF 100%);
84 -webkit-background-clip: text;
85 -webkit-text-fill-color: transparent;
86 font-size: calc(20*100vw/1920);
87 line-height: 1.6;
88 }
89 :deep(.el-statistic__number){
90 font-size: calc(26*100vw/1920);
91 font-family: 'DIN Alternate';
92 background: linear-gradient(180deg, #fff 20%, #9CD2FF 100%);
93 -webkit-background-clip: text;
94 -webkit-text-fill-color: transparent;
95 }
96 .statistic{--el-statistic-title-color: #fff;text-align: center;position: relative;
97 top: calc(-20*100vw/1920);
98 h3{color: #fff; font-family: 'YouSheBiaoTiHei';
99 background: linear-gradient(180deg, #fff 10%, #9CD2FF 100%);
100 -webkit-background-clip: text;
101 -webkit-text-fill-color: transparent;
102 font-size: calc(22*100vw/1920);
103 line-height: 1;margin: 0}
104 p{color: #fff; background: linear-gradient(180deg, #fff 20%, #9CD2FF 100%);
105 -webkit-background-clip: text; font-size: calc(26*100vw/1920);
106 font-family: 'DIN Alternate';
107 -webkit-text-fill-color: transparent;line-height: 1;overflow: visible;
108 margin: 0;height: calc(60*100vw/1920);display: flex;align-items: center;justify-content: center;
109 span{font-size: calc(22*100vw/1920);}
110 }
111 }
112 .ellipse {
113 position: relative;
114 left: -3%;
115 width: 100%;margin: auto;
116 height: 100%;
117 border-radius: 50%;z-index: 10;
118 //border: 2px #fff solid;
119 transform-style: preserve-3d;
120 transform: rotateZ(90deg) rotateY(60deg);
121 &:hover .circle{ animation-play-state: paused!important;}
122 }
123 .ellipse .circle {
124 width: calc(300*100vw/1920);
125 height: calc(400*100vw/1920);
126 top: 0;
127 left: 0;
128 right: 0;
129 bottom: 0;
130 margin: auto;
131 position: absolute;
132 text-align: center;opacity: 1;filter: brightness(100%);
133 &:hover{
134 animation-play-state: paused;
135 }
136 }
137 .ellipse .circle .ma{
138 background: url("@/assets/img/mabg.png") no-repeat center;
139 background-size: contain;
140 //box-shadow: 0 0 20px #000;
141 display: block;
142 height: calc(340*100vw/1920); width:calc(290*100vw/1920);
143 transform: rotateZ(-90deg); /* 再次旋转 */
144 img{width: 70%;position: relative;top:0;margin: 0 auto calc(60*100vw/1920);}
145 }
146
147 .ellipse .circle1{
148 animation: moveA 30s linear infinite;
149 }
150 .ellipse .circle2{
151 animation: moveB 30s linear infinite;
152 }
153 .ellipse .circle3{
154 animation: moveC 30s linear infinite;
155 }
156 .ellipse .circle4{
157 animation: moveD 30s linear infinite;
158 }
159 .ellipse .circle5{
160 animation: moveE 30s linear infinite;
161 }
162
163 @keyframes moveA {
164 0% {
165 transform: rotateZ(0) translateX(calc(300*100vw/1920)) rotateZ(0) rotateY(-70deg) scale(1);
166 filter: brightness(100%);
167 }
168 5% {
169 transform: rotateZ(80deg) translateX(calc(300*100vw/1920)) rotateZ(-80deg) rotateY(-70deg) scale(0.8);
170 filter: brightness(80%);
171 }
172 20% {
173 transform: rotateZ(80deg) translateX(calc(300*100vw/1920)) rotateZ(-80deg) rotateY(-70deg) scale(0.8);
174 filter: brightness(80%);
175 }
176 25% {
177 transform: rotateZ(160deg) translateX(calc(300*100vw/1920)) rotateZ(-160deg) rotateY(-70deg) scale(0.7);
178 filter: brightness(60%);
179 }
180 40% {
181 transform: rotateZ(160deg) translateX(calc(300*100vw/1920)) rotateZ(-160deg) rotateY(-70deg) scale(0.7);
182 filter: brightness(60%);
183 }
184 45% {
185 transform: rotateZ(200deg) translateX(calc(300*100vw/1920)) rotateZ(-200deg) rotateY(-70deg) scale(0.7);
186 filter: brightness(60%);
187 }
188 60% {
189 transform: rotateZ(200deg) translateX(calc(300*100vw/1920)) rotateZ(-200deg) rotateY(-70deg) scale(0.7);
190 filter: brightness(60%);
191 }
192 65% {
193 transform: rotateZ(280deg) translateX(calc(300*100vw/1920)) rotateZ(-280deg) rotateY(-70deg) scale(0.8);
194 filter: brightness(80%);
195 }
196 80% {
197 transform: rotateZ(280deg) translateX(calc(300*100vw/1920)) rotateZ(-280deg) rotateY(-70deg) scale(0.8);
198 filter: brightness(80%);
199 }
200 85% {
201 transform: rotateZ(360deg) translateX(calc(300*100vw/1920)) rotateZ(-360deg) rotateY(-70deg) scale(1);
202 filter: brightness(100%);
203 }
204 100% {
205 transform: rotateZ(360deg) translateX(calc(300*100vw/1920)) rotateZ(-360deg) rotateY(-70deg) scale(1);
206 filter: brightness(100%);
207 }
208 }
209 @keyframes moveB {
210 0% {
211 transform: rotateZ(-80deg) translateX(calc(300*100vw/1920)) rotateZ(80deg) rotateY(-70deg) scale(0.8);
212 filter: brightness(80%);
213 }
214 5% {
215 transform: rotateZ(0deg) translateX(calc(300*100vw/1920)) rotateZ(0deg) rotateY(-70deg) scale(1);
216 z-index: 99;filter: brightness(100%);
217 }
218 20% {
219 transform: rotateZ(0deg) translateX(calc(300*100vw/1920)) rotateZ(0deg) rotateY(-70deg) scale(1);
220 z-index: 99;filter: brightness(100%);
221 }
222 25% {
223 transform: rotateZ(80deg) translateX(calc(300*100vw/1920)) rotateZ(-80deg) rotateY(-70deg) scale(0.8);
224 filter: brightness(80%);
225 }
226 40% {
227 transform: rotateZ(80deg) translateX(calc(300*100vw/1920)) rotateZ(-80deg) rotateY(-70deg) scale(0.8);
228 filter: brightness(80%);
229 }
230 45% {
231 transform: rotateZ(160deg) translateX(calc(300*100vw/1920)) rotateZ(-160deg) rotateY(-70deg) scale(0.7);
232 filter: brightness(60%);
233 }
234 60% {
235 transform: rotateZ(160deg) translateX(calc(300*100vw/1920)) rotateZ(-160deg) rotateY(-70deg) scale(0.7);
236 filter: brightness(60%);
237 }
238 65% {
239 transform: rotateZ(200deg) translateX(calc(300*100vw/1920)) rotateZ(-200deg) rotateY(-70deg) scale(0.7);
240 filter: brightness(60%);
241 }
242 80% {
243 transform: rotateZ(200deg) translateX(calc(300*100vw/1920)) rotateZ(-200deg) rotateY(-70deg) scale(0.7);
244 filter: brightness(60%);
245 }
246 85% {
247 transform: rotateZ(280deg) translateX(calc(300*100vw/1920)) rotateZ(-280deg) rotateY(-70deg) scale(0.8);
248 filter: brightness(80%);
249 }
250 100% {
251 transform: rotateZ(280deg) translateX(calc(300*100vw/1920)) rotateZ(-280deg) rotateY(-70deg) scale(0.8);
252 filter: brightness(80%);
253 }
254 }
255 @keyframes moveC {
256 0% {
257 transform: rotateZ(-160deg) translateX(calc(300*100vw/1920)) rotateZ(160deg) rotateY(-70deg) scale(0.7);
258 filter: brightness(60%);
259 }
260 5% {
261 transform: rotateZ(-80deg) translateX(calc(300*100vw/1920)) rotateZ(80deg) rotateY(-70deg) scale(0.8);
262 filter: brightness(80%);
263 }
264 20% {
265 transform: rotateZ(-80deg) translateX(calc(300*100vw/1920)) rotateZ(80deg) rotateY(-70deg) scale(0.8);
266 filter: brightness(80%);
267 }
268 25% {
269 transform: rotateZ(0deg) translateX(calc(300*100vw/1920)) rotateZ(0deg) rotateY(-70deg) scale(1);
270 filter: brightness(100%);z-index: 99;
271 }
272 40% {
273 transform: rotateZ(0deg) translateX(calc(300*100vw/1920)) rotateZ(0deg) rotateY(-70deg) scale(1);
274 filter: brightness(100%);z-index: 99;
275 }
276 45% {
277 transform: rotateZ(80deg) translateX(calc(300*100vw/1920)) rotateZ(-80deg) rotateY(-70deg) scale(0.8);
278 filter: brightness(80%);
279 }
280 60% {
281 transform: rotateZ(80deg) translateX(calc(300*100vw/1920)) rotateZ(-80deg) rotateY(-70deg) scale(0.8);
282 filter: brightness(80%);
283 }
284 65% {
285 transform: rotateZ(160deg) translateX(calc(300*100vw/1920)) rotateZ(-160deg) rotateY(-70deg) scale(0.7);
286 filter: brightness(60%);
287 }
288 80% {
289 transform: rotateZ(160deg) translateX(calc(300*100vw/1920)) rotateZ(-160deg) rotateY(-70deg) scale(0.7);
290 filter: brightness(60%);
291 }
292 85% {
293 transform: rotateZ(200deg) translateX(calc(300*100vw/1920)) rotateZ(-200deg) rotateY(-70deg) scale(0.7);
294 filter: brightness(60%);
295 }
296 100% {
297 transform: rotateZ(200deg) translateX(calc(300*100vw/1920)) rotateZ(-200deg) rotateY(-70deg) scale(0.7);
298 filter: brightness(60%);
299 }
300 }
301 @keyframes moveD {
302 0% {
303 transform: rotateZ(-200deg) translateX(calc(300*100vw/1920)) rotateZ(200deg) rotateY(-70deg) scale(0.7);
304 filter: brightness(60%);
305 }
306 5% {
307 transform: rotateZ(-160deg) translateX(calc(300*100vw/1920)) rotateZ(160deg) rotateY(-70deg) scale(0.7);
308 filter: brightness(60%);
309 }
310 20% {
311 transform: rotateZ(-160deg) translateX(calc(300*100vw/1920)) rotateZ(160deg) rotateY(-70deg) scale(0.7);
312 filter: brightness(60%);
313 }
314 25% {
315 transform: rotateZ(-80deg) translateX(calc(300*100vw/1920)) rotateZ(80deg) rotateY(-70deg) scale(0.8);
316 filter: brightness(80%);
317 }
318 40% {
319 transform: rotateZ(-80deg) translateX(calc(300*100vw/1920)) rotateZ(80deg) rotateY(-70deg) scale(0.8);
320 filter: brightness(80%);
321 }
322 45% {
323 transform: rotateZ(0deg) translateX(calc(300*100vw/1920)) rotateZ(0deg) rotateY(-70deg) scale(1);
324 filter: brightness(100%);z-index: 99;
325 }
326 60% {
327 transform: rotateZ(0deg) translateX(calc(300*100vw/1920)) rotateZ(0deg) rotateY(-70deg) scale(1);
328 filter: brightness(100%);z-index: 99;
329 }
330 65% {
331 transform: rotateZ(80deg) translateX(calc(300*100vw/1920)) rotateZ(-80deg) rotateY(-70deg) scale(0.8);
332 filter: brightness(80%);
333 }
334 80% {
335 transform: rotateZ(80deg) translateX(calc(300*100vw/1920)) rotateZ(-80deg) rotateY(-70deg) scale(0.8);
336 filter: brightness(80%);
337 }
338 85% {
339 transform: rotateZ(160deg) translateX(calc(300*100vw/1920)) rotateZ(-160deg) rotateY(-70deg) scale(0.7);
340 filter: brightness(60%);
341 }
342 100% {
343 transform: rotateZ(160deg) translateX(calc(300*100vw/1920)) rotateZ(-160deg) rotateY(-70deg) scale(0.7);
344 filter: brightness(60%);
345 }
346 }
347 @keyframes moveE {
348 0% {
349 transform: rotateZ(-280deg) translateX(calc(300*100vw/1920)) rotateZ(280deg) rotateY(-70deg) scale(0.8);
350 filter: brightness(80%);
351 }
352 5% {
353 transform: rotateZ(-200deg) translateX(calc(300*100vw/1920)) rotateZ(200deg) rotateY(-70deg) scale(0.7);
354 filter: brightness(60%);
355 }
356 20% {
357 transform: rotateZ(-200deg) translateX(calc(300*100vw/1920)) rotateZ(200deg) rotateY(-70deg) scale(0.7);
358 filter: brightness(60%);
359 }
360 25% {
361 transform: rotateZ(-160deg) translateX(calc(300*100vw/1920)) rotateZ(160deg) rotateY(-70deg) scale(0.7);
362 filter: brightness(60%);
363 }
364 40% {
365 transform: rotateZ(-160deg) translateX(calc(300*100vw/1920)) rotateZ(160deg) rotateY(-70deg) scale(0.7);
366 filter: brightness(60%);
367 }
368 45% {
369 transform: rotateZ(-80deg) translateX(calc(300*100vw/1920)) rotateZ(80deg) rotateY(-70deg) scale(0.7);
370 filter: brightness(80%);
371 }
372 60% {
373 transform: rotateZ(-80deg) translateX(calc(300*100vw/1920)) rotateZ(80deg) rotateY(-70deg) scale(0.7);
374 filter: brightness(80%);
375 }
376 65% {
377 transform: rotateZ(0deg) translateX(calc(300*100vw/1920)) rotateZ(0deg) rotateY(-70deg) scale(1);
378 filter: brightness(100%);z-index: 99;
379 }
380 80% {
381 transform: rotateZ(0deg) translateX(calc(300*100vw/1920)) rotateZ(0deg) rotateY(-70deg) scale(1);
382 filter: brightness(100%);z-index: 99;
383 }
384 85% {
385 transform: rotateZ(80deg) translateX(calc(300*100vw/1920)) rotateZ(-80deg) rotateY(-70deg) scale(0.8);
386 filter: brightness(80%);
387 }
388 100% {
389 transform: rotateZ(80deg) translateX(calc(300*100vw/1920)) rotateZ(-80deg) rotateY(-70deg) scale(0.8);
390 filter: brightness(80%);
391 }
392 }
393 </style>
Styling with Markdown is supported
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!