894 lines
25 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<template>
<view class="activitypage">
<!-- 主导航栏 -->
<view class="main-nav">
<view class="nav-item" :class="{'nav-active': tabCur == 0}" @tap="tabSelect" :data-id="0">
累计活动
<view class="nav-line" v-if="tabCur == 0"></view>
</view>
<view class="nav-item" :class="{'nav-active': tabCur == 1}" @tap="tabSelect" :data-id="1">
啤酒币换购
<view class="nav-line" v-if="tabCur == 1"></view>
</view>
</view>
<!-- 状态提示区域 -->
<view class="status-tip" v-if="!isLoggedIn || userStatus !== 'verified'">
<view class="flex-col status-text">
<block v-if="userStatus === 'guest'">
<text class="text-lg">暂无法查看信息</text>
<text class="sub-text">您还没有登录请登录后查看信息</text>
<button class="login-btn" @click="toLogin">
<image src="@/static/send-2.svg" class="btn-icon"></image>
登录/认证
</button>
</block>
<block v-else-if="userStatus === 'unverified'">
<text class="text-lg">您的门店还未完成认证</text>
<text class="sub-text">请点击认证门店信息</text>
<button class="login-btn" @click="toLogin">
<image src="@/static/send-2.svg" class="btn-icon"></image>
去认证
</button>
</block>
<block v-else-if="userStatus === 'verifying'">
<text class="text-lg">正在认证审核中</text>
<text class="sub-text">请耐心等待</text>
</block>
</view>
</view>
<!-- 内容区域 -->
<template v-if="isLoggedIn && userStatus === 'verified'">
<!-- 状态标签栏 -->
<scroll-view scroll-x class="status-nav" :scroll-left="0">
<view class="status-nav-content">
<template v-if="tabCur == 0">
<view class="status-item" :class="{'status-active': curTag == 0}" @tap="changeTag(0)">累计中</view>
<view class="status-item" :class="{'status-active': curTag == 1}" @tap="changeTag(1)">待兑付</view>
<view class="status-item" :class="{'status-active': curTag == 2}" @tap="changeTag(2)">已兑付</view>
<view class="status-item" :class="{'status-active': curTag == 3}" @tap="changeTag(3)">已完成</view>
</template>
<template v-else>
<view class="status-item" :class="{'status-active': curCoinTag == 0}" @tap="changeCoinTag(0)">全部</view>
<view class="status-item" :class="{'status-active': curCoinTag == 1}" @tap="changeCoinTag(1)">待发货</view>
<view class="status-item" :class="{'status-active': curCoinTag == 2}" @tap="changeCoinTag(2)">已收货</view>
<view class="status-item" :class="{'status-active': curCoinTag == 3}" @tap="changeCoinTag(3)">已完成</view>
</template>
</view>
</scroll-view>
<view class="bg-white flex-col" style="height: 100%;">
<!-- 累积活动列表 -->
<scroll-view v-if="tabCur == 0" scroll-y
style="padding: 16rpx 28rpx 0;background-color: #F2F2F2;overflow-y: auto;flex:1"
@scrolltolower="changePage">
<!-- 活动列表项 -->
<view class="activity-item flex" v-for="(it, index) in myJoinList" :key="index" @click="toInfo(it)">
<!-- 左侧区域品牌logo和达成进度 -->
<view class="left flex flex-col justify-between align-center">
<!-- 品牌logo固定尺寸140x140 -->
<image :src="it.brandLogo" style="width: 140rpx;height: 140rpx;border-radius: 6rpx;">
</image>
<!-- 达成进度提示文字 -->
<view style="color: #606060;font-size: 24rpx;font-weight: bold;white-space: nowrap;">距离达成还剩</view>
<!-- 剩余数量/达标状态根据不同状态显示不同内容 -->
<view>
<!-- 累计中remainingBeerCount > 0 -->
<template v-if="it.remainingBeerCount > 0">
<text style="font-family: Roboto;font-size: 24rpx;font-weight: normal;line-height: 16rpx; text-align: center;letter-spacing: normal;color: #0B0E26;">{{ it.remainingBeerCount }}</text>
<text style="font-size: 24rpx;color: #0B0E26;"></text>
</template>
<!-- 待兑付remainingBeerCount <= 0 且未兑付 -->
<template v-else-if="it.remainingBeerCount <= 0 && !it.barAwardStatus">
<text style="font-family: Roboto;font-size: 24rpx; color: #19367A;font-weight: bold;line-height: 130%;text-align: center;letter-spacing: normal;">待兑付</text>
</template>
<!-- 已兑付厂家已兑付状态 -->
<template v-else-if="it.barAwardStatus">
<text style="font-family: Roboto;font-size: 24rpx; color: #19367A;font-weight: bold;line-height: 130%;text-align: center;letter-spacing: normal;">已兑付</text>
</template>
<!-- 已完成活动已完成状态 -->
<template v-else-if="it.activityStatus === 'COMPLETED'">
<text style="font-family: Roboto;font-size: 24rpx; color: #19367A;font-weight: bold;line-height: 130%;text-align: center;letter-spacing: normal;">已完成</text>
</template>
</view>
</view>
<!-- 右侧区域活动详细信息 -->
<view class="right">
<!-- 活动名称 -->
<view class="title">{{ it.activityName }}</view>
<!-- 活动时间首次扫码开始计算 -->
<view class="sub">时间首次扫码开始累计 <text style="color:#19367A">{{it.duration}}天内</text></view>
<!-- 活动目标累积扫码数量 -->
<view class="sub">目标全系列酒款累积扫码 {{ it.activityTarget}}</view>
<!-- 酒款图片横向滚动展示 -->
<scroll-view v-if="it.beers" scroll-x="true" class="scroll-img">
<view class="beer-box" v-for="(it, index) in it.beers" :key="index"
@click="toReview(it)">
<image v-if="it.cover" :src="it.cover" class="cover"></image>
</view>
</scroll-view>
<!-- 活动奖励信息实物或啤酒币 -->
<view class="flex align-center">
<text class="zeng"></text>
<!-- 实物奖励type=1 -->
<text v-if="it.activityRewardType == 1 && it.activityRewardGoods"
style="color: #0B0E26;font-size: 24rpx;">{{it.activityRewardGoods.goodsName}} * {{it.activityRewardCount}}</text>
<!-- 啤酒币奖励type=2 -->
<text v-if="it.activityRewardType == 2"
style="color: #0B0E26;font-size: 24rpx;">啤酒币 * {{it.activityRewardCount}}</text>
<!-- 奖励发放状态 -->
<text v-if="it.barAwardStatus"
style="color: #0B0E26;font-size: 24rpx;">已发放</text>
</view>
</view>
</view>
<!-- 列表加载状态 -->
<view class="cu-load" :class="'over'"></view>
</scroll-view>
<!-- 啤酒币换购列表 -->
<scroll-view v-if="tabCur == 1" scroll-y
style="padding: 16rpx 28rpx 0;background-color: #F2F2F2;overflow-y: auto;flex:1"
@scrolltolower="changePageCoin">
<!-- 兑换订单列表 -->
<view class="coin-item" v-for="(it, index) in myExchangeOrder" :key="index" @click="toOrderInfo(it)">
<view class="flex justify-between" style="margin-bottom: 16rpx;">
<text style="color: #5E5F60;font-weight: 600;font-size: 28rpx;">
<image src="@/static/beerCoin.png" style="width: 24rpx;height: 24rpx;margin-right: 16rpx;"></image>
啤酒币兑换</text>
<text style="color: #5E5F60;font-weight: 600;font-size: 24rpx;margin-top: 8rpx;">已完成</text>
</view>
<view class="flex justify-between">
<image :src="it.goodsCover" class="coverImg"></image>
<view class="flex justify-between flex-col flex-1" style="padding: 24rpx 0">
<text class="title word-all">{{ it.goodsName }}</text>
</view>
<view class="flex flex-col justify-center align-end">
<view class="margin-bottom">
<text class="num">{{ it.beerCoinNum}}</text>
<text class="cuIcon-rechargefill"
style="color:rgba(255, 213, 43, 1);font-size: 36rpx;margin-left: 6rpx;"></text>
</view>
<text style="color: #5E5F60;font-size: 20rpx;">{{it.redeemNum}}</text>
</view>
</view>
</view>
<view class="cu-load" :class="orderTotal == myExchangeOrder.length ? 'over': 'more'"></view>
</scroll-view>
</view>
</template>
<!-- 登录弹窗组件 -->
<loginPopup ref="loginRef" @loginSuccess="loginSuccess"></loginPopup>
</view>
</template>
<script>
import loginPopup from '@/components/loginPopup.vue';
import { myJoinListApi, getMyExchangeOrder } from "@/api/user.js"
import { getBarInfo } from "@/api/bar.js"
export default {
components: {
loginPopup
},
data() {
return {
loading: true,
userInfo: null, // 用户信息
barInfo: null, // 门店信息
isLoggedIn: false, // 登录状态
isVerified: false, // 认证状态
tabCur: 0, // 当前选中的标签页
curTag: 0, // 累积活动当前选中的标签
curCoinTag: 0, // 啤酒币换购当前选中的标签
myJoinList: [], // 我参与的活动列表
queryForm: {
status: 1, // 活动状态
pageNum: 1,
pageSize: 10
},
total: 0, // 活动总数
myExchangeOrder:[], // 兑换订单列表
orderQuery: {
pageNum: 1,
pageSize: 10
},
orderTotal: 0, // 订单总数
isLoading: false, // 是否正在加载数据
isRefreshing: false, // 是否正在刷新
};
},
computed: {
// 用户状态
userStatus() {
if (!this.isLoggedIn) return 'guest' // 游客
if (!this.barInfo || this.barInfo.authState === 0) return 'unverified' // 未认证
if (this.barInfo.authState === 1) return 'verifying' // 认证中
return 'verified' // 认证通过
}
},
onLoad() {
this.initData()
},
onShow() {
this.checkUserInfo()
},
methods: {
// 检查登录状态
async checkLoginStatus() {
try {
const token = uni.getStorageSync('token')
const userInfo = uni.getStorageSync('userInfo')
// 检查token和userInfo是否有效
if (!token || token.startsWith('temp_') || !userInfo) {
this.isLoggedIn = false
this.isVerified = false
this.userInfo = null
this.barInfo = null
return false
}
this.isLoggedIn = true
this.userInfo = userInfo
// 获取门店信息
await this.getBarInfoFun()
return true
} catch (error) {
console.error('检查登录状态失败:', error)
return false
}
},
// 获取门店信息
async getBarInfoFun() {
console.log('【getBarInfoFun】开始获取门店信息')
console.log('【getBarInfoFun】当前登录状态:', this.isLoggedIn)
if (!this.isLoggedIn) {
console.log('【getBarInfoFun】用户未登录不获取门店信息')
return
}
try {
console.log('【getBarInfoFun】调用getBarInfo接口')
const res = await getBarInfo()
console.log('【getBarInfoFun】接口返回数据:', res)
if (res.code === 200 && res.data) {
console.log('【getBarInfoFun】获取门店信息成功')
console.log('【getBarInfoFun】门店信息:', res.data)
console.log('【getBarInfoFun】认证状态(authState):', res.data.authState)
this.barInfo = res.data
this.isVerified = res.data.authState === 2 // 2表示认证通过
console.log('【getBarInfoFun】更新后的认证状态(isVerified):', this.isVerified)
uni.setStorageSync('barInfo', res.data)
console.log('【getBarInfoFun】门店信息已存储到本地')
} else {
console.log('【getBarInfoFun】获取门店信息失败接口返回异常')
this.isVerified = false
this.barInfo = null
}
} catch (error) {
console.error('【getBarInfoFun】获取门店信息出错:', error)
this.isVerified = false
this.barInfo = null
// 只在已认证状态下显示错误提示
if (this.userStatus === 'verified') {
uni.showToast({
title: '获取门店信息失败',
icon: 'none'
})
}
}
console.log('【getBarInfoFun】方法执行完成')
console.log('【getBarInfoFun】最终状态 - barInfo:', this.barInfo)
console.log('【getBarInfoFun】最终状态 - isVerified:', this.isVerified)
console.log('【getBarInfoFun】当前userStatus:', this.userStatus)
},
// 初始化数据
async initData() {
try {
this.loading = true
const isLoggedIn = await this.checkLoginStatus()
if (isLoggedIn) {
await this.getMyJoinList()
}
} catch (error) {
console.error('初始化数据失败:', error)
// 只在已认证状态下显示错误提示
if (this.userStatus === 'verified') {
uni.showToast({
title: '加载失败',
icon: 'none'
})
}
} finally {
this.loading = false
}
},
// 检查用户信息变化
async checkUserInfo() {
try {
const newToken = uni.getStorageSync('token')
const newUserInfo = uni.getStorageSync('userInfo')
// 检查token和userInfo是否有变化
if (newToken !== this.userInfo?.token ||
JSON.stringify(newUserInfo) !== JSON.stringify(this.userInfo)) {
this.loading = true
const isLoggedIn = await this.checkLoginStatus()
if (isLoggedIn) {
await this.getMyJoinList()
} else {
this.myJoinList = []
this.myExchangeOrder = []
}
}
} catch (error) {
console.error('检查用户信息失败:', error)
} finally {
this.loading = false
}
},
// 登录成功回调
async loginSuccess() {
try {
console.log('【loginSuccess】开始处理登录成功')
this.loading = true
// 获取token和openId
const token = uni.getStorageSync('token')
const openId = uni.getStorageSync('openId')
console.log('【loginSuccess】获取到的token:', token)
console.log('【loginSuccess】获取到的openId:', openId)
if (token && openId) {
// 更新登录状态
this.isLoggedIn = true
this.userInfo = {
token,
openId
}
console.log('【loginSuccess】更新登录状态:', this.isLoggedIn)
// 获取门店信息
await this.getBarInfoFun()
// 重置页面状态
this.queryForm.pageNum = 1
this.orderQuery.pageNum = 1
this.myJoinList = []
this.myExchangeOrder = []
// 重新加载数据
if (this.userStatus === 'verified') {
await this.getMyJoinList()
}
} else {
console.log('【loginSuccess】token或openId不存在')
this.isLoggedIn = false
this.userInfo = null
this.barInfo = null
this.isVerified = false
}
} catch (error) {
console.error('【loginSuccess】登录成功处理失败:', error)
// 只在已认证状态下显示错误提示
if (this.userStatus === 'verified') {
uni.showToast({
title: '登录失败',
icon: 'none'
})
}
} finally {
this.loading = false
}
},
// 获取我的兑换订单
async getMyExchangeOrderFun() {
// 如果用户未认证,直接返回
if (this.userStatus !== 'verified') {
return
}
if (this.isLoading) return
try {
this.isLoading = true
const res = await getMyExchangeOrder(this.orderQuery)
if (res && res.rows) {
this.orderTotal = res.total || 0
if (this.orderQuery.pageNum === 1) {
this.myExchangeOrder = res.rows
} else {
this.myExchangeOrder = [...this.myExchangeOrder, ...res.rows]
}
}
} catch (error) {
console.error('获取兑换订单失败:', error)
// 只在已认证状态下显示错误提示
if (this.userStatus === 'verified') {
uni.showToast({
title: '获取订单失败',
icon: 'none'
})
}
} finally {
this.isLoading = false
}
},
// 切换标签页
async tabSelect(e) {
const id = e.currentTarget.dataset.id
if (this.tabCur === id) return
this.tabCur = id
if (this.tabCur == 0) {
this.myJoinList = []
this.queryForm.pageNum = 1
await this.getMyJoinList()
} else {
this.myExchangeOrder = []
this.orderQuery.pageNum = 1
await this.getMyExchangeOrderFun()
}
},
// 获取我参与的活动列表
async getMyJoinList() {
// 如果用户未认证,直接返回
if (this.userStatus !== 'verified') {
return
}
if (this.isLoading) return
try {
this.isLoading = true
const res = await myJoinListApi(this.queryForm)
if (res && res.data) {
this.total = res.data.total || 0
let activities = []
// 处理品牌活动
if (res.data.activities && res.data.activities.length > 0) {
activities = activities.concat(res.data.activities)
}
// 处理平台活动
if (res.data.platformActivities && res.data.platformActivities.length > 0) {
activities = activities.concat(res.data.platformActivities)
}
// 根据当前选中的状态标签过滤活动
const filteredActivities = activities.filter(activity => {
switch(this.curTag) {
case 0: // 累计中
return activity.remainingBeerCount > 0
case 1: // 待兑付
return activity.remainingBeerCount <= 0 && !activity.barAwardStatus
case 2: // 已兑付
return activity.barAwardStatus
case 3: // 已完成
return activity.activityStatus === 'COMPLETED'
default:
return true
}
})
if (this.queryForm.pageNum === 1) {
this.myJoinList = filteredActivities
} else {
this.myJoinList = [...this.myJoinList, ...filteredActivities]
}
}
} catch (error) {
console.error('获取活动列表失败:', error)
// 只在已认证状态下显示错误提示
if (this.userStatus === 'verified') {
uni.showToast({
title: '获取活动列表失败',
icon: 'none'
})
}
} finally {
this.isLoading = false
}
},
// 加载更多活动
async changePage() {
if (this.myJoinList.length < this.total && !this.isLoading) {
this.queryForm.pageNum++
await this.getMyJoinList()
}
},
// 跳转到活动详情
toInfo(it) {
if (!it.batchId) return
uni.navigateTo({
url: '/pagesActivity/myActivityDetail?batchId=' + it.batchId
})
},
// 跳转到订单详情
toOrderInfo(it) {
if (!it.id || !it.goodsId) return
uni.navigateTo({
url: '/pagesCoin/orderInfo?orderId=' + it.id + '&goodsId=' + it.goodsId
})
},
// 切换活动状态标签
async changeTag(key) {
if (this.curTag === key) return
this.curTag = key
this.queryForm.pageNum = 1
this.myJoinList = []
// 设置查询状态
switch(key) {
case 0: // 累计中
this.queryForm.status = 1 // 使用整数类型
break
case 1: // 待兑付
this.queryForm.status = 2 // 使用整数类型
break
case 2: // 已兑付
this.queryForm.status = 3 // 使用整数类型
break
case 3: // 已完成
this.queryForm.status = 4 // 使用整数类型
break
default:
delete this.queryForm.status
}
await this.getMyJoinList()
},
// 切换订单状态标签
async changeCoinTag(key) {
if (this.curCoinTag === key) return
this.curCoinTag = key
this.orderQuery.pageNum = 1
this.myExchangeOrder = []
// 设置查询状态
switch(key) {
case 0:
delete this.orderQuery.status // 全部状态
break
case 1:
this.orderQuery.status = 1 // 待发货
break
case 2:
this.orderQuery.status = 2 // 已收货
break
case 3:
this.orderQuery.status = 3 // 已完成
break
}
await this.getMyExchangeOrderFun()
},
// 加载更多订单
async changePageCoin() {
if (this.myExchangeOrder.length < this.orderTotal && !this.isLoading) {
this.orderQuery.pageNum++
await this.getMyExchangeOrderFun()
}
},
// 跳转登录
toLogin() {
// 如果是未认证状态,直接跳转到认证页面
if (this.userStatus === 'unverified') {
const openId = uni.getStorageSync('openId')
uni.navigateTo({
url: '/pages/index/registration?openId=' + openId
})
} else {
// 其他状态打开登录弹窗
this.$refs.loginRef.open()
}
}
}
}
</script>
<style lang="scss" scoped>
.activitypage {
height: 100vh;
background: #FFFFFF;
display: flex;
flex-direction: column;
.main-nav {
display: flex;
justify-content: center;
align-items: center;
position: fixed;
top: 0;
left: 0;
right: 0;
z-index: 100;
padding: 0 32rpx;
background: #FFFFFF;
height: 88rpx;
box-shadow: 0 2rpx 12rpx rgba(0, 0, 0, 0.04);
.nav-item {
position: relative;
width: calc((100% - 56rpx) / 2); // 两等分宽度(减去间距)
margin: 0 14rpx; // 统一的间距
height: 100%;
display: flex;
align-items: center;
justify-content: center;
font-size: 32rpx;
color: #1A1A1A;
font-weight: normal;
transition: all 0.3s ease;
&.nav-active {
color: #4E63E0;
font-weight: 600;
.nav-line {
position: absolute;
bottom: 0;
left: 50%;
transform: translateX(-50%);
width: 48rpx;
height: 4rpx;
background: #4E63E0;
border-radius: 2rpx;
}
}
}
}
.status-nav {
position: fixed;
top: 88rpx;
left: 0;
right: 0;
z-index: 99;
background: #FFFFFF;
white-space: nowrap;
padding: 20rpx 32rpx;
// border-bottom: 1rpx solid #F5F5F5;
// box-shadow: 0rpx 1rpx 3rpx 0rpx rgba(0, 0, 0, 0.1);
.status-nav-content {
display: inline-flex;
.status-item {
display: flex;
align-items: center;
justify-content: center;
width: 147rpx;
height: 64rpx;
margin-right: 16rpx;
font-size: 24rpx;
color: #606060;
background: #f9f9f9;
border-radius: 12rpx;
&.status-active {
color: #FFF;
background: #D42E78;
}
}
}
}
.bg-white {
flex: 1;
margin-top: 172rpx; // 88rpx(导航栏) + 84rpx(标签栏)
padding-top: 24rpx; // 添加内容区域的上边距
overflow: hidden;
scroll-view {
height: 100%;
}
}
.activity-item {
border-radius: 12rpx;
background: #FFFFFF;
box-sizing: border-box;
border: 1px solid #E0E0E0;
width: 694rpx;
margin-top: 12rpx;
margin-bottom: 42rpx;
box-shadow: 0rpx 1rpx 3rpx 0rpx rgba(0, 0, 0, 0.1);
.left {
padding: 24rpx 20rpx;
border-radius: 20rpx;
background: #FFFFFF;
box-sizing: border-box;
border: 1px solid #E0E0E0;
width: 180rpx;
margin-top: -10rpx;
margin-bottom: -10rpx;
margin-left: -1rpx;
box-shadow: 0rpx 1rpx 3rpx 0rpx rgba(0, 0, 0, 0.1);
}
.right {
padding: 20rpx;
flex: 1;
.title {
font-family: Source Han Sans;
font-size: 28rpx;
font-weight: bold;
line-height: 30rpx;
color: #0B0E26;
margin-bottom: 20rpx;
}
.sub {
font-family: Source Han Sans;
font-size: 24rpx;
font-weight: 500;
line-height: 30rpx;
color: #0B0E26;
margin-bottom: 16rpx;
}
.scroll-img {
width: 470rpx;
display: flex;
flex-direction: row;
white-space: nowrap;
height: 144rpx;
margin-bottom: 20rpx;
.beer-box {
width: 100rpx;
background: #FFFFFF;
margin-right: 20rpx;
box-sizing: border-box;
display: inline-block;
.cover {
width: 100rpx;
height: 144rpx;
border-radius: 10rpx;
}
}
}
.zeng {
font-family: roboto;
font-size: 20rpx;
font-weight: bold;
line-height: normal;
text-align: center;
color: #0B0E26;
padding: 8rpx 12rpx;
border-radius: 10rpx;
background: #FEE034;
margin-right: 20rpx;
}
}
}
.coin-item {
border-radius: 12rpx;
background: #ffffff;
padding: 24rpx;
box-sizing: border-box;
margin-bottom: 32rpx;
.coverImg {
border-radius: 12rpx;
background: #E9E9E9;
width: 132rpx;
height: 176rpx;
margin-right: 24rpx;
}
.title {
font-size: 32rpx;
font-weight: 600;
color: #030303;
}
.subTitle {
font-size: 20rpx;
font-weight: 500;
color: #5E5F60;
}
.num {
font-size: 48rpx;
font-weight: 600;
color: #030303;
}
}
.status-tip {
position: fixed;
top: 88rpx;
left: 0;
right: 0;
bottom: 0;
background-color: #FDFDFD;
z-index: 99;
display: flex;
justify-content: center;
align-items: center;
.status-text {
text-align: center;
.text-lg {
color: #3D3D3D;
font-weight: 600;
font-size: 32rpx;
margin-bottom: 16rpx;
}
.sub-text {
color: #979797;
font-size: 28rpx;
margin-bottom: 32rpx;
}
.login-btn {
width: 306rpx;
height: 88rpx;
background-color: #4E63E0;
color: #FFFFFF;
font-size: 28rpx;
font-weight: 500;
display: flex;
align-items: center;
justify-content: center;
border-radius: 44rpx;
.btn-icon {
width: 48rpx;
height: 48rpx;
margin-right: 16rpx;
}
}
}
}
}
.word-all {
overflow: hidden;
text-overflow: ellipsis;
display: -webkit-box;
-webkit-line-clamp: 2;
-webkit-box-orient: vertical;
}
</style>