@@ -1,58 +1,333 @@
< script setup >
import { ref , onMounted } from "vue" ;
import { computed , nextTick , onMounted , ref } from "vue" ;
import { onLoad } from "@dcloudio/uni-app" ;
import Avatar from "@/components/Avatar.vue" ;
import {
getMvpRankList ,
getMyMvpRank ,
getMyScoreRank ,
getMyTenRingRank ,
getScoreRankList ,
getTenRingRankList ,
} from "@/apis" ;
import { capsuleHeight } from "@/util" ;
import useStore from "@/store" ;
import { storeToRefs } from "pinia" ;
const PAGE _SIZE = 10 ;
const store = useStore ( ) ;
const { user , rankData } = storeToRefs ( store ) ;
const { user } = storeToRefs ( store ) ;
const { getLvlName } = store ;
const selectedIndex = ref ( 0 ) ;
const currentList = ref ( [ ] ) ;
const myData = ref ( { } ) ;
const addBg = ref ( false ) ;
onMounted ( async ( ) => {
handleSelect ( 0 ) ;
const createRankState = ( ) => ( {
list : [ ] ,
page : 0 ,
pageSize : PAGE _SIZE ,
loading : false ,
noMore : false ,
loaded : false ,
scrollTop : 0 ,
myData : null ,
myDataLoaded : false ,
} ) ;
const h andleSelect = ( index ) => {
selectedIndex . value = index ;
myData . value = { } ;
currentList . value = [ ] ;
if ( index === 0 ) {
currentList . value = rankData . value . rank ;
} else if ( index === 1 ) {
currentList . value = rankData . value . mvpRank ;
} else if ( index === 2 ) {
currentList . value = rankData . value . ringRank ;
const r ankTabs = [
{
key : "score" ,
title : "积分榜" ,
subTitle : "排位赛积分" ,
listApi : getScoreRankList ,
myApi : getMyScoreRank ,
} ,
{
key : "mvp" ,
title : "MVP榜" ,
subTitle : "MVP次数" ,
listApi : getMvpRankList ,
myApi : getMyMvpRank ,
} ,
{
key : "tenRing" ,
title : "十环榜" ,
subTitle : "十环次数" ,
listApi : getTenRingRankList ,
myApi : getMyTenRingRank ,
} ,
] ;
// 解析 ranking 页面传入的榜单参数,进入页面时默认选中对应 tab。
const getTabIndexByRouteParam = ( tab ) => {
if ( tab === "mvp" ) return 1 ;
if ( tab === "tenRing" ) return 2 ;
return 0 ;
} ;
const rankStates = ref ( {
score : createRankState ( ) ,
mvp : createRankState ( ) ,
tenRing : createRankState ( ) ,
} ) ;
const selectedIndex = ref ( 0 ) ;
const initialTabIndex = ref ( 0 ) ;
const pageMounted = ref ( false ) ;
const initializedFromRoute = ref ( false ) ;
const addBg = ref ( false ) ;
const currentScrollTop = ref ( 0 ) ;
const restoreScrollTop = ref ( 0 ) ;
const tabSwitchAnimating = ref ( false ) ;
const suppressScrollSync = ref ( false ) ;
const suppressLoadMore = ref ( false ) ;
const stickyTabsTop = capsuleHeight + 50 ;
const stickyTabsActive = ref ( false ) ;
const tabsStickyThreshold = ref ( 0 ) ;
const tabsStickyReady = ref ( false ) ;
const tabsHeight = ref ( 0 ) ;
const getTabConfig = ( index = selectedIndex . value ) => rankTabs [ index ] ;
const getTabKey = ( index = selectedIndex . value ) => getTabConfig ( index ) . key ;
// 统一提取榜单接口返回的列表数据,兼容数组和对象两种返回格式。
const getRankListFromResponse = ( result ) => {
if ( Array . isArray ( result ) ) return result ;
if ( Array . isArray ( result ? . list ) ) return result . list ;
if ( Array . isArray ( result ? . items ) ) return result . items ;
return [ ] ;
} ;
// 为当前登录用户构造默认的个人榜单信息,避免接口未返回时底部区域缺数据。
const buildDefaultMyData = ( ) => ( {
rank : null ,
userId : user . value . id ,
name : user . value . nickName ,
avatar : user . value . avatar ,
totalScore : 0 ,
mvpCount : 0 ,
tenRings : 0 ,
totalGames : 0 ,
totalCount : 0 ,
rankName : user . value . lvlName ,
rankLvl : user . value . rankLvl ,
} ) ;
const currentTabKey = computed ( ( ) => getTabKey ( selectedIndex . value ) ) ;
const currentState = computed ( ( ) => rankStates . value [ currentTabKey . value ] ) ;
const currentList = computed ( ( ) => currentState . value . list ) ;
const currentSubTitle = computed ( ( ) => getTabConfig ( selectedIndex . value ) . subTitle ) ;
const currentMyData = computed ( ( ) => {
if ( ! user . value . id ) return null ;
return currentState . value . myData || buildDefaultMyData ( ) ;
} ) ;
// 统一格式化段位和场次文案,兼容不同接口的字段命名。
const formatLevelText = ( item = { } ) => {
const levelName = item . rankName || getLvlName ( item . rankLvl ) || "暂无段位" ;
const totalGames = item . totalGames ? ? item . TotalGames ? ? 0 ;
return ` ${ levelName } , ${ totalGames } 场 ` ;
} ;
// 统一读取榜单项的排名字段,没有后端 rank 时回退到前端序号。
const getDisplayRank = ( item = { } , index = 0 ) => {
return item . rank ? ? index + 1 ;
} ;
// 底部个人排名在未上榜时展示占位符,而不是空白。
const getDisplayMyRank = ( item = { } ) => {
return item . rank ? ? "-" ;
} ;
const getScoreValue = ( item = { } ) => item . totalScore ? ? 0 ;
const getMvpValue = ( item = { } ) => item . mvpCount ? ? item . totalScore ? ? 0 ;
const getTenRingValue = ( item = { } ) =>
item . tenRings ? ? item . TenRings ? ? item . totalScore ? ? 0 ;
// 根据当前选中的榜单类型,读取对应的展示值。
const getRankValue = ( item = { } , index = selectedIndex . value ) => {
if ( index === 0 ) return getScoreValue ( item ) ;
if ( index === 1 ) return getMvpValue ( item ) ;
return getTenRingValue ( item ) ;
} ;
const getRankUnit = ( index = selectedIndex . value ) => {
if ( index === 0 ) return "分" ;
return "次" ;
} ;
// 统一设置页面当前的视觉滚动状态,避免吸顶和顶部背景不同步。
const syncScrollVisualState = ( scrollTop = 0 ) => {
currentScrollTop . value = scrollTop ;
addBg . value = scrollTop > 100 ;
if ( ! tabsStickyReady . value ) {
stickyTabsActive . value = false ;
return ;
}
if ( user . value . id ) {
currentList . value . some ( ( item ) => {
if ( item . userId === user . value . id ) {
myData . value = item ;
return true ;
}
return false ;
} ) ;
if ( ! myData . value . userId ) {
myData . value = {
userId : user . value . id ,
TotalGames : 0 ,
totalScore : 0 ,
mvpCount : 0 ,
TenRings : 0 ,
} ;
stickyTabsActive . value = scrollTop >= tabsStickyThreshold . value ;
} ;
// 只保留一条滚动恢复链路:从当前滚动位置平滑滚到目标位置,避免多套控制同时生效造成闪烁。
const applyScrollPosition = async (
fromScrollTop = currentScrollTop . value ,
toScrollTop = 0 ,
withAnimation = false
) => {
tabSwitchAnimating . value = withAnimation ;
restoreScrollTop . value = fromScrollTop ;
await nextTick ( ) ;
restoreScrollTop . value = toScrollTop ;
syncScrollVisualState ( toScrollTop ) ;
} ;
// 请求指定榜单的某一页数据,只有当前榜单会追加分页,不影响其他榜单的浏览状态。
const loadRankPage = async ( tabKey , { reset = false } = { } ) => {
const state = rankStates . value [ tabKey ] ;
const config = rankTabs . find ( ( item ) => item . key === tabKey ) ;
if ( ! config || state . loading ) return ;
if ( ! reset && state . noMore ) return ;
const nextPage = reset ? 1 : state . page + 1 ;
state . loading = true ;
if ( reset ) state . noMore = false ;
try {
const result = await config . listApi ( undefined , nextPage , PAGE _SIZE ) ;
const list = getRankListFromResponse ( result ) ;
state . list = reset ? list : state . list . concat ( list ) ;
state . page = nextPage ;
state . loaded = true ;
state . noMore = list . length < PAGE _SIZE ;
} catch ( error ) {
if ( reset ) {
state . list = [ ] ;
state . page = 0 ;
state . loaded = false ;
state . noMore = false ;
}
uni . showToast ( {
title : "排行榜加载失败" ,
icon : "none" ,
} ) ;
console . error ( "load rank page error" , error ) ;
} finally {
state . loading = false ;
}
} ;
const onScrollView = ( e ) => {
addBg . value = e . detail . scrollTop > 100 ;
// 每个榜单独立请求一次个人排名信息,切回该榜单时直接复用,避免打断浏览上下文。
const loadMyRankData = async ( tabKey ) => {
if ( ! user . value . id ) return ;
const state = rankStates . value [ tabKey ] ;
const config = rankTabs . find ( ( item ) => item . key === tabKey ) ;
if ( ! config || state . myDataLoaded ) return ;
try {
const result = await config . myApi ( ) ;
state . myData = {
... buildDefaultMyData ( ) ,
... ( result || { } ) ,
} ;
} catch ( error ) {
state . myData = buildDefaultMyData ( ) ;
console . error ( "load my rank data error" , error ) ;
} finally {
state . myDataLoaded = true ;
}
} ;
const subTitles = [ "排位赛积分" , "MVP次数" , "十环次数" ] ;
// 首次进入或切换到未加载过的榜单时,初始化它的分页数据和个人横条数据。
const ensureTabReady = async ( index = selectedIndex . value ) => {
const tabKey = getTabKey ( index ) ;
const state = rankStates . value [ tabKey ] ;
if ( ! state . loaded ) {
await loadRankPage ( tabKey , { reset : true } ) ;
}
if ( user . value . id && ! state . myDataLoaded ) {
await loadMyRankData ( tabKey ) ;
}
await nextTick ( ) ;
return state . scrollTop || 0 ;
} ;
onLoad ( ( options = { } ) => {
initialTabIndex . value = getTabIndexByRouteParam ( options . tab ) ;
selectedIndex . value = initialTabIndex . value ;
if ( pageMounted . value && ! initializedFromRoute . value ) {
initializePage ( ) ;
}
} ) ;
// 页面初始化同时兼容 onLoad 和 onMounted 的先后顺序,确保首屏一定落到路由指定的榜单。
const initializePage = async ( ) => {
if ( initializedFromRoute . value ) return ;
initializedFromRoute . value = true ;
const nextScrollTop = await ensureTabReady ( selectedIndex . value ) ;
await applyScrollPosition ( 0 , nextScrollTop , false ) ;
setTimeout ( ( ) => {
measureTabsMetrics ( ) ;
} , 0 ) ;
} ;
onMounted ( async ( ) => {
pageMounted . value = true ;
await initializePage ( ) ;
} ) ;
// 切换榜单时保留原榜单的列表和滚动位置,切回来后继续从之前的位置浏览。
const handleSelect = async ( index ) => {
if ( index === selectedIndex . value ) return ;
const previousTabKey = currentTabKey . value ;
rankStates . value [ previousTabKey ] . scrollTop = currentScrollTop . value ;
const previousScrollTop = currentScrollTop . value ;
suppressScrollSync . value = true ;
suppressLoadMore . value = true ;
selectedIndex . value = index ;
const nextScrollTop = await ensureTabReady ( index ) ;
await applyScrollPosition ( previousScrollTop , nextScrollTop , false ) ;
setTimeout ( ( ) => {
tabSwitchAnimating . value = false ;
suppressScrollSync . value = false ;
suppressLoadMore . value = false ;
} , 220 ) ;
} ;
// 触底后只加载当前榜单的下一页数据,其他榜单的数据和页码保持不变。
const loadMore = async ( ) => {
if ( suppressLoadMore . value ) return ;
await loadRankPage ( currentTabKey . value ) ;
} ;
// 实时记录当前榜单的滚动位置,切换回来时恢复到上一次浏览位置。
const onScrollView = ( e ) => {
const scrollTop = e . detail . scrollTop || 0 ;
if ( suppressScrollSync . value ) return ;
syncScrollVisualState ( scrollTop ) ;
rankStates . value [ currentTabKey . value ] . scrollTop = scrollTop ;
} ;
// 计算 tab 在滚动内容中的真实位置和高度,作为吸顶切换的唯一依据。
const measureTabsMetrics = ( ) => {
const query = uni . createSelectorQuery ( ) ;
query
. select ( "#rank-list-content-start" )
. boundingClientRect ( )
. select ( ".rank-tabs-anchor" )
. boundingClientRect ( )
. exec ( ( res = [ ] ) => {
const [ startRect , rect ] = res ;
if ( ! startRect || ! rect ) return ;
const tabOffset = rect . top - startRect . top ;
tabsStickyThreshold . value = Math . max ( 0 , tabOffset - 92 ) ;
tabsHeight . value = rect . height || 0 ;
tabsStickyReady . value = true ;
syncScrollVisualState ( currentScrollTop . value ) ;
} ) ;
} ;
< / script >
< template >
@@ -65,7 +340,7 @@ const subTitles = ["排位赛积分", "MVP次数", "十环次数"];
>
< image
: style = "{ opacity: addBg ? 1 : 0 }"
src = ".. /static/app-bg.png"
src = "https://static.shelingxingqiu.com/shootmini /static/app-bg.png"
mode = "widthFix"
/ >
< navigator open -type = " navigateBack " >
@@ -75,18 +350,32 @@ const subTitles = ["排位赛积分", "MVP次数", "十环次数"];
< / view >
< scroll-view
scroll -y
:scroll-with-animation = "tabSwitchAnimating"
:scroll-top = "restoreScrollTop"
@scroll ="onScrollView"
: style = "{ height: myData.userId ? '90vh' : '100vh' } "
@scrolltolower ="loadMore "
: style = "{ height: user.id ? '90vh' : '100vh' }"
>
< view id = "rank-list-content-start" class = "content-start-anchor" > < / view >
< image
src = "https://static.shelingxingqiu.com/attachment/2025-09-25/dd1p9b3wcrwnlnghiq.png"
mode = "widthFix"
class = "header-bg"
@load ="measureTabsMetrics"
/ >
< view class = "rank-tabs" >
< view
v-if = "stickyTabsActive"
class = "rank-tabs-placeholder"
: style = "{ height: `${tabsHeight}px` }"
/ >
< view
class = "rank-tabs rank-tabs-anchor"
: class = "{ 'rank-tabs-anchor-fixed': stickyTabsActive }"
: style = "stickyTabsActive ? { top: `${stickyTabsTop}px` } : {}"
>
< view
v-for = "(rankType, index) in ['积分榜', 'MVP榜', '十环榜'] "
:key = "index "
v-for = "(rankType, index) in rankTabs "
:key = "rankType.key "
: style = "{
fontSize: index === selectedIndex ? '16px' : '14px',
color: index === selectedIndex ? '#000' : '#fff',
@@ -94,18 +383,18 @@ const subTitles = ["排位赛积分", "MVP次数", "十环次数"];
}"
@tap ="handleSelect(index)"
>
{ { rankType } }
{ { rankType . title } }
< / view >
< / view >
< view class = "rank-list" >
< view class = "rank-list-header" >
< text > 排名 < / text >
< text > 用户ID < / text >
< text > { { subTitles [ selectedIndex ] } } < / text >
< text > { { currentSubTitle } } < / text >
< / view >
< view
v-for = "(item, index) in currentList"
: key= "index "
: key= "`${currentTabKey}-${index}-${item.userId || item.name}` "
class = "rank-list-item"
: style = "{
backgroundColor: index % 2 === 0 ? '#9898981f' : 'transparent',
@@ -147,65 +436,60 @@ const subTitles = ["排位赛积分", "MVP次数", "十环次数"];
src = "../static/champ3.png"
mode = "widthFix"
/ >
< view v-if = "index > 2" class="view-crown" > {{ index + 1 }} < / view >
< view v-if = "index > 2" class="view-crown" >
{{ getDisplayRank ( item , index ) }}
< / view >
< Avatar :src = "item.avatar" / >
< view class = "rank-item-content" >
< text class = "truncate" > { { item . name } } < / text >
< text > { { getLvlName ( item . rankLvl ) } } , { { item . TotalGames } } 场 < / text >
< text > { { formatLevelText ( item ) } } < / text >
< / view >
< text class = "rank-item-integral" v-if = "selectedIndex === 0" >
< text class = "rank-item-integral" >
< text
: style = "{ fontSize: '14px', color: '#fff', marginRight: '5px' }"
> { { item . totalScore } } < / t e x t
> 分
< / text >
< text class = "rank-item-integral" v-if = "selectedIndex === 1" >
< text
: style = "{ fontSize: '14px', color: '#fff', marginRight: '5px' }"
> { { item . mvpCount } } < / t e x t
> 次
< / text >
< text class = "rank-item-integral" v-if = "selectedIndex === 2" >
< text
: style = "{ fontSize: '14px', color: '#fff', marginRight: '5px' }"
> { { item . TenRings } } < / t e x t
> 次
>
{ { getRankValue ( item ) } }
< / text >
{ { getRankUnit ( ) } }
< / text >
< / view >
< view v-if = "!currentList.length" class="no-data" >
< text > 筹备中 ... < / text >
< view
v-if = "currentState.loading && !currentList.length"
class = "no-data"
>
< text > 加载中 ... < / text >
< / view >
< view
v-else-if = "!currentState.loading && !currentList.length"
class = "no-data"
>
< text > 暂无数据 < / text >
< / view >
< view v-else class = "list-tip" >
< text v-if = "currentState.loading" > 加载中... < / text >
< text v-else-if = "currentState.noMore" > 没有更多了 < / text >
< / view >
< / view >
< / scroll -view >
< view class = "my-rank-data" v-if = "myData.userId " >
< view class = "my-rank-data" v-if = "currentMyData " >
< image
src = "https://static.shelingxingqiu.com/attachment/2025-08-05/dbuaf19pf7qd8ps0uh.png"
mode = "widthFix"
/ >
< text > { { myData . rank } } < / text >
< Avatar : src= "user.avatar" / >
< text > { { getDisplayMyRank ( currentMyData ) } } < / text >
< Avatar : src= "currentMyData.avatar || user.avatar" / >
< view class = "rank-item-content" >
< text class = "truncate" > { { user . nickName } } < / text >
< text > { { user . lvlName } } , { { myData . TotalGames } } 场 < / text >
< text class = "truncate" > { { currentMyData . name || user. nickName } } < / text >
< text > { { formatLevelText ( currentMyData ) } } < / text >
< / view >
< text class = "rank-item-integral" v-if = "selectedIndex === 0" >
< text class = "rank-item-integral" >
< text
: style = "{ fontSize: '14px', color: '#fff', marginRight: '5px' }"
> { { myData . totalScore || 0 } } < / t e x t
> 分 < / t e x t
>
< text class = "rank-item-integral" v-if = "selectedIndex === 1" >
< text
: style = "{ fontSize: '14px', color: '#fff', marginRight: '5px' }"
> { { myData . mvpCount || 0 } } < / t e x t
> 次 < / t e x t
>
< text class = "rank-item-integral" v-if = "selectedIndex === 2" >
< text
: style = "{ fontSize: '14px', color: '#fff', marginRight: '5px' }"
> { { myData . TenRings || 0 } } < / t e x t
> 次 < / t e x t
>
>
{ { getRankValue ( currentMyData ) } }
< / text >
{ { getRankUnit ( ) } }
< / text >
< / view >
< / view >
< / template >
@@ -214,9 +498,16 @@ const subTitles = ["排位赛积分", "MVP次数", "十环次数"];
. container {
width : 100 % ;
}
. content - start - anchor {
width : 100 % ;
height : 0 ;
}
. header - bg {
width : 100 % ;
}
. header {
width : 100 % ;
height : 50 px ;
@@ -227,6 +518,7 @@ const subTitles = ["排位赛积分", "MVP次数", "十环次数"];
z - index : 10 ;
overflow : hidden ;
}
. header - back {
width : 22 px ;
height : 22 px ;
@@ -234,6 +526,7 @@ const subTitles = ["排位赛积分", "MVP次数", "十环次数"];
margin - top : 5 px ;
position : relative ;
}
. header > image : first - child {
width : 100 vw ;
height : 100 vh ;
@@ -242,25 +535,40 @@ const subTitles = ["排位赛积分", "MVP次数", "十环次数"];
left : 0 ;
transition : all 0.5 s ease ;
}
. header > text {
color : # fff ;
font - weight : bold ;
transition : all 0.5 s ease ;
position : relative ;
}
. rank - tabs {
width : calc ( 100 % - 20 px ) ;
display : flex ;
justify - content : space - around ;
padding : 0 10 px ;
margin - top : - 15 px ;
padding : 20 rpx 10 px ;
}
. rank - tabs > view {
width : 25 % ;
padding : 10 px ;
text - align : center ;
border - radius : 20 px ;
}
. rank - tabs - placeholder {
width : 100 % ;
}
. rank - tabs - anchor - fixed {
position : fixed ;
left : 0 ;
z - index : 11 ;
background : # 000000 ;
backdrop - filter : blur ( 8 px ) ;
}
. rank - list {
display : flex ;
flex - direction : column ;
@@ -268,11 +576,12 @@ const subTitles = ["排位赛积分", "MVP次数", "十环次数"];
width : calc ( 100 % - 20 px ) ;
color : # fff9 ;
font - size : 12 px ;
margin : 10 px ;
margin : 0 10 px 10 px 10px ;
border : 1 px solid rgb ( 255 217 71 / 0.2 ) ;
border - radius : 10 px ;
background - color : # 313131 ;
}
. rank - list > view {
display : flex ;
align - items : center ;
@@ -281,20 +590,25 @@ const subTitles = ["排位赛积分", "MVP次数", "十环次数"];
overflow : hidden ;
position : relative ;
}
. rank - list - header {
width : calc ( 100 % - 20 px ) ! important ;
padding : 10 px ;
}
. rank - list - header > text : nth - child ( 2 ) {
width : 14 % ;
}
. rank - list - header > text : last - child {
width : 30 % ;
text - align : right ;
}
. rank - list - item {
padding : 10 px 0 ;
}
. player - bg {
position : absolute ;
width : 100 % ;
@@ -302,12 +616,14 @@ const subTitles = ["排位赛积分", "MVP次数", "十环次数"];
top : 0 ;
left : 0 ;
}
. player - crown {
position : relative ;
width : 27 px ;
height : 27 px ;
margin : 0 15 px ;
}
. view - crown {
width : 27 px ;
height : 27 px ;
@@ -319,6 +635,7 @@ const subTitles = ["排位赛积分", "MVP次数", "十环次数"];
background - color : # 676767 ;
position : relative ;
}
. rank - item - content {
display : flex ;
flex - direction : column ;
@@ -328,17 +645,20 @@ const subTitles = ["排位赛积分", "MVP次数", "十环次数"];
position : relative ;
padding - left : 10 px ;
}
. rank - item - content > text : first - child {
color : # fff ;
font - size : 14 px ;
margin - bottom : 3 px ;
width : 120 px ;
}
. rank - list - item > text : last - child {
margin - right : 10 px ;
width : 56 px ;
text - align : right ;
}
. my - rank - data {
width : calc ( 100 % - 30 px ) ;
padding : 15 px ;
@@ -352,12 +672,14 @@ const subTitles = ["排位赛积分", "MVP次数", "十环次数"];
overflow : hidden ;
border - radius : 10 px ;
}
. my - rank - data > image : first - child {
position : absolute ;
width : 100 % ;
left : 0 ;
top : - 5 px ;
}
. my - rank - data > text : nth - child ( 2 ) {
background - color : # c1a434 ;
position : relative ;
@@ -369,20 +691,24 @@ const subTitles = ["排位赛积分", "MVP次数", "十环次数"];
min - width : 15 px ;
text - align : center ;
}
. my - rank - data > text : last - child {
position : relative ;
margin - right : 10 px ;
width : 65 px ;
text - align : right ;
}
. my - rank - data > . rank - item - content > text : first - child {
color : # fed847 ;
}
. my - rank - data > . rank - item - integral {
color : # fff9 ;
font - size : 12 px ;
margin - right : 0 ! important ;
}
. no - data {
width : 100 % ;
height : 400 px ;
@@ -392,4 +718,11 @@ const subTitles = ["排位赛积分", "MVP次数", "十环次数"];
color : # fff9 ;
font - size : 14 px ;
}
. list - tip {
justify - content : center ! important ;
color : # fff9 ;
font - size : 12 px ;
min - height : 60 rpx ;
}
< / style >