This commit is contained in:
那些花儿
2025-09-25 21:09:52 +08:00
parent 4a651fa9bc
commit 43ed86e638
6 changed files with 816 additions and 57 deletions
+75 -41
View File
@@ -243,7 +243,6 @@ layout("/layouts/v4/baseLayout.html"){
try {
debugger
const app = JSON.parse(window.sessionStorage.getItem("zhgh_sub_app"))
$("#sub-app-container #sidebar-menu .menu-header .menu-title").text(app?.name)
} catch (e) {
@@ -324,53 +323,52 @@ layout("/layouts/v4/baseLayout.html"){
if (res.code === 0) {
this.menus = res.data
window.sessionStorage.setItem("zhgh_sub_app_menus", JSON.stringify(res.data))
this.echoMenus()
this.matchUrlToMenu()
this.echoMenus()
// this.matchUrlToMenu()
} else {
this.menus = []
}
})
},
// 按 URL 精准激活
matchUrlToMenu() {
// 跳转带过来的地址
const pathname = window.location.pathname
const find = (list, parentIds = []) => {
for (const m of list) {
if (m.href && pathname.includes(m.href.split('?')[0])) {
return { menu: m, parentIds }
}
if (m.children?.length) {
const hit = find(m.children, [...parentIds, m.id])
if (hit) return hit
}
}
return null
}
const hit = find(this.menus)
if (hit) {
// 激活跳转菜单
this.activeMenuIndex = hit.menu.id
this.openedMenus = hit.parentIds
const app = JSON.parse(window.sessionStorage.getItem("zhgh_sub_app"))
$("#sub-app-container #sidebar-menu .menu-header .menu-title").text(app?.name)
this.$nextTick(() => {
this.menuSelect(hit.menu.id, hit.parentIds)
// 保证内容区对应
commonUtil.pjaxPush(hit.menu.href)
})
} else if (!this.activeMenuIndex) {
// 没命中且缓存也没有 → 再降级到第一个
this.defaultSelect()
}
},
// 按 URL 精准激活
matchUrlToMenu() {
// 跳转带过来的地址
const pathname = window.location.pathname
const find = (list, parentIds = []) => {
for (const m of list) {
if (m.href && pathname.includes(m.href.split('?')[0])) {
return {menu: m, parentIds}
}
if (m.children?.length) {
const hit = find(m.children, [...parentIds, m.id])
if (hit) return hit
}
}
return null
}
const hit = find(this.menus)
if (hit) {
// 激活跳转菜单
this.activeMenuIndex = hit.menu.id
this.openedMenus = hit.parentIds
const app = JSON.parse(window.sessionStorage.getItem("zhgh_sub_app"))
$("#sub-app-container #sidebar-menu .menu-header .menu-title").text(app?.name)
this.$nextTick(() => {
this.menuSelect(hit.menu.id, hit.parentIds)
// 保证内容区对应
commonUtil.pjaxPush(hit.menu.href)
})
} else if (!this.activeMenuIndex) {
// 没命中且缓存也没有 → 再降级到第一个
this.defaultSelect()
}
},
// 设置应用信息
setAppInfo(app) {
if (app) {
debugger
// 储存到缓存
window.sessionStorage.setItem("zhgh_sub_app", JSON.stringify(app))
// 储存到div中
@@ -388,14 +386,50 @@ layout("/layouts/v4/baseLayout.html"){
console.log(this.openedMenus)
console.log(this.activeMenuIndex)
if (!this.activeMenuIndex) {
if (!this.activeMenuIndex && '/platform/v4/subApp' === window.location.pathname) {
this.defaultSelect()
} else {
this.hrefSelect()
}
} catch (e) {
}
},
// 地址选中
hrefSelect() {
function findMenuPath(menus, targetHref) {
function search(items, path) {
for (const item of items) {
// 如果当前项匹配 href,返回路径(包含自己)
if (item.href === targetHref) {
return [...path, item];
}
// 如果有子菜单,递归查找
if (item.children?.length) {
const result = search(item.children, [...path, item]);
if (result) return result;
}
}
return null;
}
return search(menus, []);
}
const result = findMenuPath(this.menus, window.location.pathname)
this.activeMenuIndex = result[result.length-1]
this.openedMenus = result.map(v=>v.id)
this.$nextTick(() => {
this.menuSelect(this.activeMenuIndex, this.openedMenus)
// 使用pjax跳转
commonUtil.pjaxPush(self.href)
})
},
// 默认选中
defaultSelect() {
// 查找第一个有href的子菜单
+11 -10
View File
@@ -13,21 +13,20 @@ const act = {
<!-- 活动数据 - Swiper -->
<div class="swiper activity-swiper">
<div class="swiper-wrapper">
<div class="swiper-slide" v-for="(activity, index) in actList" :key="index">
<div class="swiper-slide" v-for="(activity, index) in actList" :key="activity.id">
<div class="item" @click="go(activity)">
<div class="img-box">
<img :src="activity.image || 'https://www.ncu.edu.cn/__local/8/52/2C/644986B4C9A030F7B65300178A6_8679CB08_18467.jpg'"
<img :src="activity.cover1 || 'https://www.ncu.edu.cn/__local/8/52/2C/644986B4C9A030F7B65300178A6_8679CB08_18467.jpg'"
alt="">
</div>
<h4 class="title">
{{ activity.title || '欢迎参加周末电影鉴赏活动' }}
{{ activity.name}}
</h4>
<!--报名时间-->
<div class="time">
<p>
<i class="fa fa-clock-o"></i>
报名时间:{{ activity.startTime || '2017-05-01' }}至{{ activity.endTime ||
'2017-05-05' }}
时间:{{ activity.startDate }}至{{ activity.endDate }}
</p>
</div>
</div>
@@ -56,10 +55,10 @@ const act = {
listAct() {
this.$axios.post("/platform/home/listHomeActivity").then((res) => {
if (res.code === 0) {
for (let i = 0; i < 10; i++) {
this.actList = this.actList.concat(res.data)
}
// this.actList = res.data
// for (let i = 0; i < 10; i++) {
// this.actList = this.actList.concat(res.data)
// }
this.actList = res.data
// 数据加载完成后初始化Swiper
this.$nextTick(() => {
this.initSwiper()
@@ -124,6 +123,7 @@ const act = {
font-weight: bold;
position: relative;
text-align: center;
padding: 40px 0;
}
.section-act .section-act-title span:hover {
@@ -162,7 +162,7 @@ const act = {
.activity-swiper {
width: 100%;
padding: 0 50px;
padding: 0 50px 20px 50px;
}
.activity-swiper .swiper-slide {
@@ -237,6 +237,7 @@ const act = {
.activity-swiper .swiper-slide .item h4 {
font-size: 20px;
margin-top: 10px;
height: 60px;
color: #333;
display: -webkit-box;
-webkit-line-clamp: 2;
@@ -0,0 +1,300 @@
const entry = {
template: /*language=HTML*/ `
<div class="entry-wrapper">
<div class="entry-title">
常用入口
</div>
<div class="entry-container">
<!-- 左侧分类导航 -->
<div class="sidebar">
<div class="category" :class="{active: activeCategory === 'serv'}"
@click="setActiveCategory('serv')">
<i class="fa fa-star"></i>
<span>推荐服务</span>
</div>
<div class="category" :class="{active: activeCategory === 'app'}" @click="setActiveCategory('app')">
<i class="fa fa-fire"></i>
<span>推荐应用</span>
</div>
<div class="category" :class="{active: activeCategory === 'fav'}"
@click="setActiveCategory('fav')">
<i class="fa fa-heart"></i>
<span>收藏服务</span>
</div>
</div>
<!-- 右侧服务卡片区域 -->
<div class="content">
<div class="services-grid">
<div class="service-card" v-for="(service, index) in currentServices" :key="index"
@click="openService(service)">
<div class="service-icon">
<img :src="service.picIcon">
</div>
<div class="service-info">
<h4 class="service-name">{{ service.name }}</h4>
</div>
</div>
</div>
</div>
</div>
</div>
`,
data() {
return {
activeCategory: 'serv',
hasMore: true,
entries: {
serv: [],
app: [],
fav: []
},
}
},
computed: {
currentServices() {
return this.entries[this.activeCategory] || [];
}
},
created() {
this.getRecommendService()
this.getRecommendApp()
this.getFavorite()
},
methods: {
setActiveCategory(category) {
this.activeCategory = category;
},
// 查询推荐服务
async getRecommendService() {
this.$axios.post('/platform/home/listRecommendService', {platform: "PC"}).then(res => {
if (res.code === 0) {
this.entries.serv = res.data
}
})
},
// 获取推荐应用
async getRecommendApp() {
this.$axios.post('/platform/home/listRecommendApp', {platform: "PC"}).then(res => {
if (res.code === 0) {
this.entries.app = res.data
}
})
},
// 获取我的收藏
async getFavorite() {
this.$axios.post('/platform/home/listFavorite', {platform: "PC"}).then(res => {
if (res.code === 0) {
this.entries.fav = res.data
}
})
},
// 点击服务
openService(service) {
if(this.activeCategory === 'serv'){
if(!service.href) this.$message.error('无效的链接地址')
window.open(service.href)
return
}
if(this.activeCategory === 'app'){
// 储存到缓存
window.sessionStorage.setItem("zhgh_sub_app", JSON.stringify(service))
// 新标签页打开
window.open("/platform/v4/subApp?appId=" + service.id, "_blank")
return
}
if(this.activeCategory === 'fav'){
if(!service.href) this.$message.error('无效的链接地址')
window.open(service.href)
return
if(!service.parentId){
// 储存到缓存
window.sessionStorage.setItem("zhgh_sub_app", JSON.stringify(app))
// 新标签页打开
window.open("/platform/v4/subApp?appId=" + app.id, "_blank")
}
}
}
},
style: /*language=CSS*/ `
.entry-wrapper {
width: 100%;
background-image: url(https://www.ncu.edu.cn/images/bbg1.jpg);
background-size: cover;
background-position: center;
background-repeat: no-repeat;
}
.entry-title {
font-size: 30px;
color: #000000;
display: block;
font-weight: bold;
position: relative;
text-align: center;
padding: 40px 0;
}
.entry-container {
width: 80%;
max-width: 80%;
margin: 0 auto;
padding: 20px;
display: flex;
gap: 30px;
overflow: hidden;
}
.sidebar {
width: 200px;
flex-shrink: 0;
display: flex;
flex-direction: column;
justify-content: space-between;
}
.category {
display: flex;
align-items: center;
padding: 12px 16px;
margin-bottom: 2px;
cursor: pointer;
transition: background-color 0.2s ease;
border-left: 3px solid transparent;
}
.category:hover {
}
.category.active {
color: var(--color-primary);
}
.category i {
font-size: 14px;
margin-right: 10px;
width: 16px;
text-align: center;
}
.category span {
font-size: 18px;
font-weight: 700;
}
.content {
flex: 1;
height: 164px;
}
.services-grid {
display: grid;
grid-template-columns: repeat(auto-fill, minmax(200px, 1fr));
gap: 20px;
grid-template-rows: repeat(2, 1fr);
overflow: hidden;
}
.service-card {
padding: 12px;
height: 72px;
cursor: pointer;
transition: background-color 0.2s ease;
border: none;
background: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAYEAAAB4CAYAAAAUs05BAAAACXBIWXMAABYlAAAWJQFJUiTwAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAANrSURBVHgB7dzNapNZAMfh0zbNYGgosYql4wiCFEEZXLiYG3DrdryPuQbvpXMB7t24m4UOCiKuEtCKsaVNiTRaXhshLvyoSd/Yzf95oORA827PLycn5yxsdZ/crKql+6WG1uLy0d3Lm29Pes+jfm+1N9w/VwD4qXtXbmyf9P/Hu29Wng/6K6WOqnq6WACI1ZgM1pqt0Z31qztlBoMPh0sPXr+8OMsztzsbe9fanfcFgG9sdZ+tz/L+6+0LB7c6lw5meWZ7OGg+7HfPj8dWAgDBRAAgmAgABBMBgGAiABBMBACCiQBAsIV5nBiehXMCAD826zmBWpwYBsi2UFXV5vHrP6WGycnhae4QAuD0JncGneak8He8sBIACCYCAMEa//b+bx5vDJ/dRgQAtY2/EprDVdJ9KwGAYLWukgbgbI03g+tuCLtKGoDPRAAgmAgABBMBgGAiABBMBACCiQBAMBEACCYCAMFEACCYCAAEEwGAYCIAEEwEAIKJAEAwEQAIJgIAwUQAIJgIAAQTAYBgIgAQTAQAgokAQDARAAgmAgDBRAAgmAgABBMBgGAiABBMBACCiQBAMBEACCYCAMFEACCYCAAEEwGAYCIAEEwEAIKJAEAwEQAIJgIAwUQAIJgIAAQTAYBgIgAQTAQAgokAQDARAAgmAgDBRAAgmAgABBMBgGAiABBMBACCiQBAMBEACCYCAMFEACCYCAAEEwGAYCIAEEwEAIKJAEAwEQAIJgIAwUQAIJgIAAQTAYBgIgAQTAQAgokAQDARAAgmAgDBRAAgmAgABBMBgGAiABBMBACCiQBAMBEACCYCAMFEACCYCAAEEwGAYCIAEKwxGbwbDZtb3WfrpYbW4vLR3cubbwsAv8Tj3Tcrzwf9lTInVgIAwRp///Hn6Ph1u9Qw+HC49OD1y4sFgDNxvX3h4Fbn0kGpZ8dKACCYCAAEW9jqPrlZVUv3yymtNVujv9Y29qb9Ouh2Z2PvWrvzvgDwjWl+oLM/OlwefBw1fm+1682lVfXUSgAg2JefiI4/0d9Zv7oz7YPbw0HzYb97fjxuL/92dO/KjRM3lx/1e6u94f65AsBPnTSnTubfWeftr58fj60EAIKJAEAwEQAIJgIAwUQAIJgIAAQTAYBgc71Kehr/7b5aHf8VAGqZx7xtJQAQ7BOP4saDQA2PwQAAAABJRU5ErkJggg==) no-repeat;
background-size: 100% 100%;
display: flex;
align-items: center;
gap: 12px;
}
.service-card:hover {
}
.service-icon {
width: 32px;
height: 32px;
flex-shrink: 0;
}
.service-icon img {
width: 100%;
height: 100%;
border-radius: 4px;
object-fit: cover;
}
.service-info {
flex: 1;
min-width: 0;
overflow: hidden;
}
.service-name {
font-size: 14px;
font-weight: 400;
color: #333;
margin: 0;
line-height: 1.4;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
/* 响应式设计 */
@media (max-width: 768px) {
.entry-container {
flex-direction: column;
gap: 20px;
}
.sidebar {
width: 100%;
display: flex;
overflow-x: auto;
gap: 0;
border-bottom: 1px solid #e8e8e8;
padding-bottom: 0;
}
.category {
flex-shrink: 0;
margin-bottom: 0;
white-space: nowrap;
border-left: none;
border-bottom: 3px solid transparent;
}
.category.active {
border-left: none;
border-bottom-color: #1890ff;
}
.services-grid {
grid-template-columns: repeat(auto-fill, minmax(160px, 1fr));
}
}
@media (max-width: 480px) {
.services-grid {
grid-template-columns: 1fr 1fr;
}
.service-card {
padding: 12px;
}
}
`
}
@@ -22,6 +22,18 @@ layout("/layouts/v4/baseLayout.html"){
object-fit: cover;
}
.section-wrapper {
width: 100%;
}
.act-wrapper{
width: 100%;
background-image: url(https://www.ncu.edu.cn/images/bbg1.jpg);
background-size: cover;
background-position: center center;
background-repeat: no-repeat;
}
</style>
@@ -33,7 +45,18 @@ layout("/layouts/v4/baseLayout.html"){
<img src="${config.AppHomeImg!}" alt=""/>
</div>
</div>
<act/>
<user></user>
<entry></entry>
<!-- 工会活动 -->
<div class="section-wrapper act-wrapper">
<act/>
</div>
<jcdt :list="websiteNews.grassroots"></jcdt>
</div>
<!-- 引入Swiper JS -->
@@ -41,19 +64,35 @@ layout("/layouts/v4/baseLayout.html"){
<script>
<!--#include("act.js"){}#-->
<!--#include("jcdt.js"){}#-->
<!--#include("entry.js"){}#-->
<!--#include("user.js"){}#-->
new Vue({
el: '#v4-home-app',
data: {
data(){
return{
websiteNews:{
grassroots:[],
}
}
},
components: {
'act': act
'act': act,
'jcdt': jcdt,
'entry': entry,
'user': user,
},
mounted() {
this.getWebSiteNews()
},
methods: {
getWebSiteNews(){
this.$axios.post('/platform/home/getNews').then(res => {
if (res.code === 0) {
this.websiteNews = res.data
}
})
}
}
})
</script>
@@ -0,0 +1,137 @@
const jcdt = {
template: /*language=HTML*/ `
<div class="jcdt-wrapper">
<div class="jcdt-container">
<div class="jcdt-title">
基层动态
</div>
<div class="jcdt-content">
<div class="jcdt-list">
<div class="jcdt-item" v-for="item in list" :key="item.title">
<div class="date">{{item.date}}</div>
<div class="title">{{item.title}}</div>
<div class="image">
<img :src="item.image" alt="">
</div>
<div class="summary">{{item.summary}}</div>
</div>
</div>
</div>
</div>
</div>
`,
data() {
return {}
},
props: {
list: {
type: Array,
default: []
}
},
methods: {},
style: /*language=CSS*/ `
.jcdt-wrapper {
width: 100%;
background-image: url(https://cdgh.ncu.edu.cn/images/index_bg2.png);
background-size: cover;
background-position: center;
background-repeat: no-repeat;
}
.jcdt-container {
width: 80%;
max-width: 80%;
margin: 0 auto;
}
.jcdt-title{
font-size: 30px;
color: #000000;
display: block;
font-weight: bold;
position: relative;
text-align: center;
padding: 40px 0;
}
.jcdt-list {
display: grid;
grid-template-columns: repeat(4, 1fr);
gap: 20px;
}
.jcdt-item {
display: flex;
flex-direction: column;
padding: 16px;
border: none;
border-bottom: 3px solid transparent;
transition: all 0.3s ease;
cursor: pointer;
height: auto;
}
.jcdt-item:hover{
background: #ffffff;
border-bottom-color: var(--color-primary);
transform: translateY(-4px);
box-shadow: 0 8px 20px rgba(0, 0, 0, 0.15);
}
.jcdt-item .date {
font-size: 20px;
font-weight: bold;
white-space: nowrap;
text-align: left;
margin-bottom: 8px;
transition: opacity 0.3s ease;
}
.jcdt-item .title {
font-size: 16px;
font-weight: 600;
margin-bottom: 12px;
line-height: 1.4;
display: -webkit-box;
-webkit-line-clamp: 2;
-webkit-box-orient: vertical;
overflow: hidden;
height: 45px;
}
.jcdt-item .image {
width: 100%;
height: 180px;
margin: 0 0 16px 0;
border-radius: 8px;
overflow: hidden;
background: #f5f5f5;
display: flex;
align-items: center;
justify-content: center;
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
transition: transform 0.3s ease;
}
.jcdt-item .image img {
width: 100%;
height: 100%;
object-fit: cover;
transition: transform 0.3s ease;
}
.jcdt-item .summary {
font-size: 14px;
color: #666;
line-height: 1.6;
display: -webkit-box;
-webkit-line-clamp: 3;
-webkit-box-orient: vertical;
overflow: hidden;
text-align: justify;
margin-bottom: 12px;
}
`
}
@@ -0,0 +1,248 @@
const user = {
template: /*language=HTML*/ `
<div class="user-wrapper">
<div class="user-container">
<div class="user-info-section">
<div class="user-details">
<div class="user-name">${@auth.getPrincipalProperty('username')}</div>
<div class="user-meta">
<div class="meta-item">
<span class="meta-label">工号:</span>
<span class="meta-value">${@auth.getPrincipalProperty('loginname')}</span>
</div>
<div class="meta-item">
<span class="meta-label">单位:</span>
<span class="meta-value">
<!--#if(!isEmpty(@auth.getPrincipalProperty('unit'))){#-->
${@auth.getPrincipalProperty('unit').getName()}
<!--#}#-->
</span>
</div>
<div class="meta-item">
<span class="meta-label">分工会:</span>
<span class="meta-value">
<!--#if(!isEmpty(@auth.getPrincipalProperty('union'))){#-->
${@auth.getPrincipalProperty('union').getName()}
<!--#}#-->
</span>
</div>
</div>
</div>
</div>
<div class="stats-section">
<div class="stats-grid">
<div class="stat-item pending" @click="handleStatClick('todo')">
<div class="stat-icon">
<i class="fa fa-clock-o"></i>
</div>
<div class="stat-content">
<div class="stat-label">待办</div>
<div class="stat-number">{{ stats.todoCount }}</div>
</div>
</div>
<div class="stat-item completed" @click="handleStatClick('done')">
<div class="stat-icon">
<i class="fa fa-check-circle"></i>
</div>
<div class="stat-content">
<div class="stat-label">已办</div>
<div class="stat-number">{{ stats.doneCount }}</div>
</div>
</div>
<div class="stat-item messages" @click="handleStatClick('notification')">
<div class="stat-icon">
<i class="fa fa-bell"></i>
</div>
<div class="stat-content">
<div class="stat-label">消息</div>
<div class="stat-number">{{ stats.notifications }}</div>
</div>
</div>
<div class="stat-item reminders" @click="handleStatClick('started')">
<div class="stat-icon">
<i class="fa fa-file-text"></i>
</div>
<div class="stat-content">
<div class="stat-label">发起</div>
<div class="stat-number">{{ stats.startedCount }}</div>
</div>
</div>
</div>
</div>
</div>
</div>
`,
data() {
return {
stats: {
todoCount: 0,
doneCount: 0,
notifications: 0,
startedCount: 0
}
}
},
methods: {
handleStatClick(type) {
debugger
if (['todo', 'done', 'application'].includes(type)) {
window.open('/flow/todoCenter?status=' + type)
}
},
loadStats() {
this.$axios.post("/flow/todoCenter/statistics").then(res => {
if (res.code === 0) {
this.stats = res.data;
}
})
}
},
mounted() {
this.loadStats();
},
style: /*language=CSS*/ `
.user-wrapper {
width: 100%;
background-image: url(https://www.ncu.edu.cn/images/bbg1.jpg);
background-size: cover;
background-position: center;
background-repeat: no-repeat;
}
.user-container {
width: 80%;
max-width: 80%;
margin: 0 auto;
padding: 20px;
display: flex;
gap: 30px;
overflow: hidden;
}
.user-info-section {
display: flex;
align-items: center;
min-width: 0;
width: 390px;
background-image: url(https://cdgh.ncu.edu.cn/images/index_bg2.png);
background-size: cover;
background-position: center;
background-repeat: no-repeat;
padding: 12px;
}
.user-details {
flex: 1;
min-width: 0;
}
.user-name {
font-size: 20px;
font-weight: 600;
color: #1a1a1a;
margin-bottom: 12px;
}
.user-meta {
display: flex;
flex-direction: column;
gap: 6px;
}
.meta-item {
display: flex;
align-items: center;
font-size: 14px;
}
.meta-label {
color: #666;
min-width: 60px;
flex-shrink: 0;
}
.meta-value {
color: #333;
font-weight: 500;
}
/* 右侧统计区域 */
.stats-section {
flex: 1;
min-width: 0;
}
.stats-grid {
display: grid;
grid-template-columns: repeat(4, 1fr);
gap: 32px;
height: 100%;
}
.stat-item {
display: flex;
align-items: flex-start;
gap: 12px;
cursor: pointer;
transition: all 0.3s ease;
padding: 16px;
position: relative;
background: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAYEAAAB4CAYAAAAUs05BAAAACXBIWXMAABYlAAAWJQFJUiTwAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAANrSURBVHgB7dzNapNZAMfh0zbNYGgosYql4wiCFEEZXLiYG3DrdryPuQbvpXMB7t24m4UOCiKuEtCKsaVNiTRaXhshLvyoSd/Yzf95oORA827PLycn5yxsdZ/crKql+6WG1uLy0d3Lm29Pes+jfm+1N9w/VwD4qXtXbmyf9P/Hu29Wng/6K6WOqnq6WACI1ZgM1pqt0Z31qztlBoMPh0sPXr+8OMsztzsbe9fanfcFgG9sdZ+tz/L+6+0LB7c6lw5meWZ7OGg+7HfPj8dWAgDBRAAgmAgABBMBgGAiABBMBACCiQBAsIV5nBiehXMCAD826zmBWpwYBsi2UFXV5vHrP6WGycnhae4QAuD0JncGneak8He8sBIACCYCAMEa//b+bx5vDJ/dRgQAtY2/EprDVdJ9KwGAYLWukgbgbI03g+tuCLtKGoDPRAAgmAgABBMBgGAiABBMBACCiQBAMBEACCYCAMFEACCYCAAEEwGAYCIAEEwEAIKJAEAwEQAIJgIAwUQAIJgIAAQTAYBgIgAQTAQAgokAQDARAAgmAgDBRAAgmAgABBMBgGAiABBMBACCiQBAMBEACCYCAMFEACCYCAAEEwGAYCIAEEwEAIKJAEAwEQAIJgIAwUQAIJgIAAQTAYBgIgAQTAQAgokAQDARAAgmAgDBRAAgmAgABBMBgGAiABBMBACCiQBAMBEACCYCAMFEACCYCAAEEwGAYCIAEEwEAIKJAEAwEQAIJgIAwUQAIJgIAAQTAYBgIgAQTAQAgokAQDARAAgmAgDBRAAgmAgABBMBgGAiABBMBACCiQBAMBEACCYCAMFEACCYCAAEEwGAYCIAEKwxGbwbDZtb3WfrpYbW4vLR3cubbwsAv8Tj3Tcrzwf9lTInVgIAwRp///Hn6Ph1u9Qw+HC49OD1y4sFgDNxvX3h4Fbn0kGpZ8dKACCYCAAEW9jqPrlZVUv3yymtNVujv9Y29qb9Ouh2Z2PvWrvzvgDwjWl+oLM/OlwefBw1fm+1682lVfXUSgAg2JefiI4/0d9Zv7oz7YPbw0HzYb97fjxuL/92dO/KjRM3lx/1e6u94f65AsBPnTSnTubfWeftr58fj60EAIKJAEAwEQAIJgIAwUQAIJgIAAQTAYBgc71Kehr/7b5aHf8VAGqZx7xtJQAQ7BOP4saDQA2PwQAAAABJRU5ErkJggg==) no-repeat;
background-size: 100% 100%;
}
.stat-item:hover {
transform: translateY(-2px);
}
.stat-icon {
position: absolute;
top: 12px;
right: 12px;
width: 32px;
height: 32px;
display: flex;
align-items: center;
justify-content: center;
border-radius: 6px;
font-size: 16px;
color: #999;
}
.stat-icon i {
font-size: 32px;
color: var(--color-primary-3);
}
.stat-content {
flex: 1;
min-width: 0;
display: flex;
flex-direction: column;
gap: 8px;
}
.stat-label {
font-size: 16px;
color: #333;
font-weight: 700;
line-height: 1;
text-align: center;
padding: 15px 0;
}
.stat-number {
font-size: 32px;
font-weight: 700;
color: var(--color-primary);
line-height: 1;
flex: 1;
text-align: center;
}
`
}