deploy: auto commit repo-root changes 2026-08-03 02:48:38

This commit is contained in:
hajimi
2026-08-03 02:48:38 +08:00
parent 56b34414ac
commit 622921f64b
2 changed files with 601 additions and 193 deletions
@@ -139,7 +139,7 @@ $line: #e8ebef;
color: $text;
&__nav {
height: 104rpx;
height: 96rpx;
padding: 0 36rpx;
display: flex;
align-items: center;
@@ -150,7 +150,7 @@ $line: #e8ebef;
&__back {
width: 80rpx;
color: #111827;
font-size: 76rpx;
font-size: 64rpx;
font-family: Arial, sans-serif;
font-weight: 200;
line-height: 70rpx;
@@ -158,7 +158,7 @@ $line: #e8ebef;
}
&__title {
font-size: 40rpx;
font-size: 36rpx;
font-weight: 700;
letter-spacing: 2rpx;
}
@@ -166,26 +166,26 @@ $line: #e8ebef;
&__rules {
width: 150rpx;
color: $blue;
font-size: 30rpx;
font-size: 26rpx;
text-align: right;
}
&__scroll {
height: calc(100vh - 104rpx);
height: calc(100vh - 96rpx);
box-sizing: border-box;
}
&__bottom-button {
margin: 28rpx 38rpx 0;
height: 92rpx;
margin: 24rpx 38rpx 0;
height: 80rpx;
display: flex;
align-items: center;
justify-content: center;
border-radius: 28rpx;
border-radius: 24rpx;
color: #fff;
background: linear-gradient(100deg, #0869ed, #277ff1);
box-shadow: 0 12rpx 26rpx rgba(8, 105, 237, .18);
font-size: 32rpx;
font-size: 28rpx;
font-weight: 700;
}
@@ -196,7 +196,7 @@ $line: #e8ebef;
.points-card {
position: relative;
height: 304rpx;
height: 280rpx;
margin: 0 36rpx 20rpx;
overflow: hidden;
border-radius: 28rpx;
@@ -206,49 +206,49 @@ $line: #e8ebef;
&__content {
position: relative;
z-index: 2;
padding: 42rpx 0 0 50rpx;
padding: 36rpx 0 0 44rpx;
}
&__label {
display: block;
font-size: 32rpx;
font-size: 28rpx;
font-weight: 600;
}
&__value {
display: block;
margin-top: 20rpx;
font-size: 82rpx;
margin-top: 16rpx;
font-size: 72rpx;
line-height: 1;
font-weight: 800;
}
&__desc {
display: block;
margin-top: 22rpx;
font-size: 28rpx;
margin-top: 18rpx;
font-size: 24rpx;
}
&__detail {
position: absolute;
right: 34rpx;
bottom: 44rpx;
right: 28rpx;
bottom: 36rpx;
z-index: 3;
height: 68rpx;
padding: 0 28rpx;
height: 60rpx;
padding: 0 24rpx;
display: flex;
align-items: center;
gap: 14rpx;
border-radius: 22rpx;
border-radius: 18rpx;
color: $blue;
background: #fff;
box-shadow: 0 10rpx 20rpx rgba(4, 65, 150, .14);
font-size: 28rpx;
font-size: 25rpx;
font-weight: 600;
}
&__detail-icon {
font-size: 34rpx;
font-size: 30rpx;
line-height: 1;
}
@@ -294,11 +294,11 @@ $line: #e8ebef;
.quick-item {
position: relative;
height: 144rpx;
padding: 0 42rpx;
height: 124rpx;
padding: 0 34rpx;
display: flex;
align-items: center;
gap: 26rpx;
gap: 20rpx;
box-sizing: border-box;
&:nth-child(odd) {
@@ -310,8 +310,8 @@ $line: #e8ebef;
}
&__icon {
width: 70rpx;
height: 70rpx;
width: 60rpx;
height: 60rpx;
flex-shrink: 0;
display: flex;
align-items: center;
@@ -319,12 +319,12 @@ $line: #e8ebef;
border-radius: 50%;
color: $blue;
background: #edf4ff;
font-size: 48rpx;
font-size: 40rpx;
line-height: 1;
}
&__label {
font-size: 30rpx;
font-size: 26rpx;
font-weight: 600;
white-space: nowrap;
}
@@ -332,7 +332,7 @@ $line: #e8ebef;
&__arrow {
margin-left: auto;
color: #8b929e;
font-size: 46rpx;
font-size: 38rpx;
font-family: Arial, sans-serif;
font-weight: 200;
}
@@ -353,12 +353,12 @@ $line: #e8ebef;
display: flex;
align-items: center;
color: $muted;
font-size: 26rpx;
font-size: 24rpx;
}
&__arrow {
margin-left: 8rpx;
font-size: 38rpx;
font-size: 34rpx;
line-height: 1;
}
}
@@ -372,8 +372,8 @@ $line: #e8ebef;
}
.detail-item {
min-height: 116rpx;
padding: 22rpx 0;
min-height: 100rpx;
padding: 18rpx 0;
display: flex;
align-items: center;
box-sizing: border-box;
@@ -383,15 +383,15 @@ $line: #e8ebef;
}
&__icon {
width: 70rpx;
height: 70rpx;
margin-right: 26rpx;
width: 60rpx;
height: 60rpx;
margin-right: 20rpx;
flex-shrink: 0;
display: flex;
align-items: center;
justify-content: center;
border-radius: 20rpx;
font-size: 40rpx;
font-size: 34rpx;
}
&__icon--expense {
@@ -409,32 +409,32 @@ $line: #e8ebef;
flex: 1;
display: flex;
flex-direction: column;
gap: 8rpx;
gap: 6rpx;
}
&__title {
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
font-size: 28rpx;
font-size: 25rpx;
font-weight: 600;
}
&__time,
&__status {
color: $muted;
font-size: 24rpx;
font-size: 21rpx;
}
&__amount {
margin-left: 18rpx;
margin-left: 14rpx;
flex-shrink: 0;
display: flex;
flex-direction: column;
align-items: flex-end;
gap: 8rpx;
gap: 6rpx;
color: #151922;
font-size: 30rpx;
font-size: 26rpx;
font-weight: 700;
}
@@ -452,15 +452,15 @@ $line: #e8ebef;
.points-tip {
margin: 20rpx 40rpx 0;
min-height: 68rpx;
padding: 0 24rpx;
min-height: 60rpx;
padding: 0 20rpx;
display: flex;
align-items: center;
gap: 14rpx;
border-radius: 20rpx;
color: #738096;
background: #eef5ff;
font-size: 24rpx;
font-size: 22rpx;
&__icon {
color: $blue;
@@ -1,162 +1,115 @@
<template>
<view class="lottery-page" :class="{ 'page-no-scroll': showAiPopup }">
<!-- 顶部导航 -->
<view class="lottery-nav" :style="{ paddingTop: statusBarHeight + 'px' }">
<view class="lottery-nav__content">
<image v-if="websiteLogo" class="lottery-nav__logo" :src="websiteLogo" mode="aspectFit" />
<text class="lottery-nav__title">彩票中心</text>
<AiAssistantEntry size="compact" align="right" />
</view>
<view class="lottery-nav__right" @tap="showSharePopup = true">
<u-icon name="share" size="36" color="#333" />
<view class="lottery-brand">
<view class="lottery-brand__logo">
<image v-if="websiteLogo" :src="websiteLogo" mode="aspectFit" />
<text v-else>SB</text>
</view>
<text class="lottery-nav__title">彩票中心</text>
</view>
<view class="lottery-nav__tools">
<AiAssistantEntry size="compact" align="right" />
<view class="lottery-nav__share" @tap="showSharePopup = true">
<u-icon name="share" size="34" color="#1468e8" />
</view>
</view>
</view>
</view>
<!-- 一级分类Tab -->
<scroll-view scroll-x class="game-category-tabs">
<view class="game-category-tabs__inner">
<view v-for="cat in gameCategories" :key="cat.value" class="game-category-tab"
:class="{ 'game-category-tab--active': currentGameCategory === cat.value }"
@tap="switchGameCategory(cat.value)">
<text class="game-category-tab__label">{{ cat.label }}</text>
<view class="hall-tabs">
<view v-for="tab in hallTabs" :key="tab.value" class="hall-tab"
:class="{ 'hall-tab--active': tab.value === 'hall' }" @tap="switchHallTab(tab.value)">
<text>{{ tab.label }}</text>
</view>
</view>
<scroll-view v-if="currentGames.length" scroll-x class="lottery-games" :show-scrollbar="false">
<view class="lottery-games__inner">
<view v-for="game in currentGames" :key="game.code" class="lottery-game-chip"
:class="{ 'lottery-game-chip--active': isGameChipActive(game) }" @tap="selectGame(game)">
<view v-if="game.icon" class="lottery-game-chip__icon">
<image :src="game.icon" mode="aspectFit" />
</view>
<text>{{ game.name }}</text>
</view>
<view class="lottery-game-chip lottery-game-chip--all" @tap="selectAllGames">
<text>全部</text>
<u-icon name="arrow-right" size="26" color="#7d8797" />
</view>
</view>
</scroll-view>
<view v-else class="lottery-games__empty"><text>暂无彩种</text></view>
<!-- 二级彩种网格 -->
<view v-if="currentGames.length" class="game-grid">
<view v-for="game in currentGames" :key="game.code" class="game-grid__item"
:class="{ 'game-grid__item--active': selectedGameCode === game.code }" @tap="selectGame(game)">
<view class="game-grid__icon"
:class="game.icon ? '' : 'game-grid__icon--' + game.template.toLowerCase()">
<image v-if="game.icon" class="game-grid__icon-img" :src="game.icon" mode="aspectFit" />
<text v-else class="game-grid__icon-text">{{ game.name.substring(0, 2) }}</text>
</view>
<text class="game-grid__name">{{ game.name }}</text>
<text class="game-grid__count">日开{{ game.open_count }}</text>
</view>
</view>
<view v-else class="game-grid__empty">
<text>暂无彩种</text>
<view class="lottery-disclaimer">
<view class="lottery-disclaimer__icon"><u-icon name="shield" size="30" color="#7ea5df" /></view>
<text>开奖信息仅供参考请理性参与</text>
</view>
<!-- 下期预测选中彩种时显示 -->
<view v-if="selectedGameCode && nextDrawInfo" class="predict-card">
<view class="predict-card__header">
<view class="predict-card__left">
<text class="predict-card__name">{{ selectedGameName }}</text>
<view class="predict-card__badge">
<text></text>
<text class="predict-card__issue">{{ nextDrawInfo.next_issue }}</text>
<text></text>
</view>
</view>
<view class="predict-card__right">
<text class="predict-card__date">{{ fmtDate(nextDrawInfo.draw_date) }}</text>
<view class="predict-card__status">
<text>待开奖</text>
</view>
<view class="latest-section">
<view class="latest-section__header">
<text class="latest-section__title">最新开奖</text>
<view class="latest-section__refresh" @tap="refreshLatest">
<text>更新于 {{ latestUpdatedAt }}</text>
<u-icon name="reload" size="30" color="#758091" />
</view>
</view>
<view class="predict-card__body">
<view class="predict-card__countdown">
<view class="predict-card__clock-icon">
<text class="predict-card__clock-svg">🕐</text>
</view>
<text class="predict-card__countdown-text">{{ getCountdown(nextDrawInfo.next_time) || '即将开奖'
}}</text>
</view>
<view class="predict-card__ai-btn" @tap="openAiPopup({ category_id: 0, code: selectedGameCode })">
<view class="predict-card__star predict-card__star--left"></view>
<view class="predict-card__ai-badge">AI</view>
<text class="predict-card__ai-text"> 智能预测</text>
<view class="predict-card__star predict-card__star--right"></view>
</view>
</view>
</view>
<!-- 最新开奖卡片 -->
<view v-for="draw in latestDraws" :key="draw.code + draw.issue" class="latest-card">
<view class="latest-card__header">
<view class="latest-card__left">
<view class="latest-card__logo">
<image v-if="draw.icon" class="latest-card__logo-img" :src="draw.icon" mode="aspectFit" />
<text v-else class="latest-card__logo-text">{{ (draw.game_name || '').substring(0, 1) }}</text>
</view>
<view class="latest-card__meta">
<text class="latest-card__name">{{ draw.game_name }}</text>
<view class="latest-card__sub">
<text class="latest-card__period"><text class="latest-card__issue">{{ draw.issue
}}</text></text>
<text class="latest-card__date">{{ fmtDate(draw.draw_time) }}</text>
</view>
</view>
</view>
<view class="latest-card__right">
<view v-if="draw.next_issue" class="latest-card__next-row">
<text class="latest-card__next-label">下一期</text>
<text class="latest-card__next-issue">{{ draw.next_issue }}</text>
</view>
<text v-if="draw.next_time && getCountdown(draw.next_time)" class="latest-card__cd">{{
getCountdown(draw.next_time) }}</text>
</view>
</view>
<view class="latest-card__divider"></view>
<view v-if="draw.numbers?.length" class="latest-card__balls">
<template v-for="(ball, i) in draw.numbers" :key="i">
<text v-if="i === draw.numbers.length - 1" class="ball__plus">+</text>
<view class="ball-wrap">
<view class="ball"
:class="'ball--' + (ball.color || (i === draw.numbers.length - 1 ? 'blue' : 'red'))">
<text class="ball__num">{{ formatNum(ball.num ?? ball) }}</text>
</view>
<text v-if="ball.zodiac" class="ball-zodiac">{{ ball.zodiac }}</text>
</view>
</template>
</view>
<view class="latest-card__ai" @tap="goAiPredict(draw)">
<text class="latest-card__ai-badge">AI</text>
<text class="latest-card__ai-text">{{ getLatestAiText(draw) }}</text>
<text class="latest-card__ai-arrow"></text>
</view>
</view>
<!-- 历史开奖选中彩种时显示 -->
<view v-if="selectedGameCode && drawList.length" class="draw-section">
<view class="draw-section__header">
<text class="draw-section__title">{{ selectedGameName }} 开奖历史</text>
</view>
<view v-for="item in drawList" :key="item.code + item.issue" class="draw-item">
<view class="draw-item__head">
<text class="draw-item__cat">{{ item.game_name || item.code }}</text>
<text class="draw-item__period"> {{ item.issue }} </text>
<text class="draw-item__date">{{ fmtDate(item.draw_time) }}</text>
<view class="draw-item__status" :class="{ 'draw-item__status--pending': !item.numbers?.length }">
<text>{{ item.numbers?.length ? '已开奖' : '待开奖' }}</text>
</view>
</view>
<view v-if="item.numbers?.length" class="draw-item__balls">
<template v-for="(ball, i) in item.numbers" :key="i">
<text v-if="i === item.numbers.length - 1" class="ball__plus ball__plus--sm">+</text>
<view class="ball-wrap ball-wrap--sm">
<view class="ball ball--sm"
:class="'ball--' + (ball.color || (i === item.numbers.length - 1 ? 'blue' : 'red'))">
<text class="ball__num">{{ formatNum(ball.num ?? ball) }}</text>
<view v-if="!latestDraws.length" class="latest-empty"><text>暂无开奖数据</text></view>
<view v-for="draw in latestDraws" :key="draw.code + draw.issue" class="latest-card">
<view class="latest-card__body">
<view class="latest-card__main">
<view class="latest-card__identity">
<view class="latest-card__logo">
<image v-if="draw.icon" :src="draw.icon" mode="aspectFit" />
<text v-else>{{ (draw.game_name || '').substring(0, 1) }}</text>
</view>
<view class="latest-card__meta">
<text class="latest-card__name">{{ draw.game_name || draw.code }}</text>
<view class="latest-card__issue-row">
<text>{{ draw.issue }}</text>
<text class="latest-card__status">已开奖</text>
</view>
<text class="latest-card__date">开奖时间 {{ fmtDate(draw.draw_time) }}</text>
</view>
<text v-if="ball.zodiac" class="ball-zodiac ball-zodiac--sm">{{ ball.zodiac }}</text>
</view>
</template>
<view v-if="draw.numbers?.length" class="latest-card__balls">
<template v-for="(ball, i) in draw.numbers" :key="i">
<text v-if="i === draw.numbers.length - 1" class="ball__plus">+</text>
<view class="ball-wrap">
<view class="ball"
:class="'ball--' + (ball.color || (i === draw.numbers.length - 1 ? 'blue' : 'red'))">
<text class="ball__num">{{ formatNum(ball.num ?? ball) }}</text>
</view>
<text v-if="ball.zodiac" class="ball-zodiac">{{ ball.zodiac }}</text>
</view>
</template>
</view>
</view>
<view class="latest-card__next">
<view class="latest-card__next-row" @tap="goDrawHistory(draw)">
<text>下期开奖</text>
<text class="latest-card__next-issue">{{ getNextIssue(draw) }}</text>
<u-icon name="arrow-right" size="26" color="#7c8797" />
</view>
<text class="latest-card__next-label">距离开奖还有</text>
<text class="latest-card__countdown">{{ getCountdown(draw.next_time) || '--:--:--' }}</text>
<view class="latest-card__countdown-labels"><text></text><text></text><text></text></view>
</view>
</view>
<view v-else class="draw-item__pending">
<text class="draw-item__pending-text">等待开奖...</text>
<view class="latest-card__divider" />
<view class="latest-card__actions">
<view class="latest-card__action" @tap="goDrawDetail(draw)">
<u-icon name="file-text" size="34" color="#1468e8" />
<text>查看详情</text>
</view>
<view class="latest-card__action" @tap="goDrawHistory(draw)">
<u-icon name="clock" size="34" color="#1468e8" />
<text>历史开奖</text>
</view>
</view>
</view>
<view v-if="drawLoading" class="draw-loading">
<text>加载中...</text>
</view>
<view v-if="!drawLoading && drawNoMore" class="draw-nomore">
<text>没有更多了</text>
</view>
</view>
<!-- AI分析弹窗 -->
@@ -267,12 +220,18 @@ import SharePopup from '@/components/share-popup/share-popup.vue'
import { AI_DAILY_FREE_TEXT, getAiFreeRemain } from '@/config/ai'
const showSharePopup = ref(false)
const hallTabs = [
{ label: '开奖大厅', value: 'hall' },
{ label: '我的关注', value: 'following' },
{ label: '开奖日历', value: 'calendar' }
]
const appStore = useAppStore()
const websiteLogo = computed(() => appStore.getWebsiteConfig.shop_logo || '')
const statusBarHeight = ref(0)
const latestDraws = ref<any[]>([])
const latestUpdatedAt = ref('--:--')
const gameSelections = ref<Record<number, { code: string; name: string }>>(uni.getStorageSync('lottery_selections') || {})
const selectedGameCode = ref('')
const selectedGameName = ref('')
@@ -325,6 +284,25 @@ const currentGames = computed(() => {
return cat?.games || []
})
const switchHallTab = (value: string) => {
if (value === 'hall') return
uni.showToast({ title: '功能即将开放', icon: 'none' })
}
const isGameChipActive = (game: any) => {
if (selectedGameCode.value) return selectedGameCode.value === game.code
return game.code === currentGames.value[0]?.code
}
const selectAllGames = () => {
selectedGameCode.value = ''
selectedGameName.value = ''
drawList.value = []
delete gameSelections.value[currentGameCategory.value]
saveSelections()
fetchLatest()
}
const fetchGameList = async () => {
try {
const data = await getLotteryGameList()
@@ -369,6 +347,27 @@ const selectGame = (game: any) => {
fetchLatest()
}
const refreshLatest = () => {
fetchLatest(true)
}
const getNextIssue = (draw: any) => {
if (draw?.next_issue) return draw.next_issue
const issue = Number(draw?.issue)
return Number.isFinite(issue) && issue > 0 ? String(issue + 1) : '待定'
}
const goDrawDetail = (draw: any) => {
if (!draw?.code || !draw?.issue) return
uni.navigateTo({ url: `/packages_lottery/pages/detail?code=${draw.code}&issue=${draw.issue}` })
}
const goDrawHistory = (draw: any) => {
if (!draw?.code) return
const name = encodeURIComponent(draw.game_name || draw.code)
uni.navigateTo({ url: `/packages_lottery/pages/draw_list?code=${draw.code}&name=${name}` })
}
const fmtDate = (s: string) => {
if (!s) return ''
@@ -381,7 +380,7 @@ const formatNum = (n: any) => {
return num < 10 ? '0' + num : String(num)
}
const fetchLatest = async () => {
const fetchLatest = async (showFeedback = false) => {
try {
const data = await getLatestDrawResult()
const allList = Array.isArray(data) ? data : data ? [data] : []
@@ -389,16 +388,15 @@ const fetchLatest = async () => {
const iconMap: Record<string, string> = {}
allGames.forEach((g: any) => { if (g.icon) iconMap[g.code] = g.icon })
let filtered: any[]
if (selectedGameCode.value) {
filtered = allList.filter((d: any) => d.code === selectedGameCode.value)
} else {
const codes = currentGames.value.map((g: any) => g.code)
filtered = codes.length ? allList.filter((d: any) => codes.includes(d.code)) : allList
}
const codes = currentGames.value.map((g: any) => g.code)
filtered = codes.length ? allList.filter((d: any) => codes.includes(d.code)) : allList
filtered.forEach((d: any) => { d.icon = iconMap[d.code] || '' })
latestDraws.value = filtered
latestUpdatedAt.value = new Date().toTimeString().slice(0, 5)
if (showFeedback) uni.showToast({ title: '已更新', icon: 'none' })
} catch (e) {
console.log('获取最新开奖失败=>', e)
if (showFeedback) uni.showToast({ title: '更新失败,请稍后重试', icon: 'none' })
}
}
@@ -1646,4 +1644,414 @@ onReachBottom(() => {
color: #333;
}
}
/* 彩票中心设计稿视觉层 */
.lottery-page {
min-height: 100vh;
background: #fff;
color: #1b2230;
padding-bottom: 32rpx;
}
.lottery-nav {
background: #fff;
border-bottom: 1rpx solid #eef1f5;
&__content {
min-height: 108rpx;
display: flex;
align-items: center;
justify-content: space-between;
padding: 0 32rpx;
}
&__tools {
display: flex;
align-items: center;
gap: 20rpx;
}
&__share {
width: 62rpx;
height: 62rpx;
display: flex;
align-items: center;
justify-content: center;
}
&__title {
font-size: 42rpx;
font-weight: 700;
color: #171b24;
letter-spacing: 1rpx;
}
}
.lottery-brand {
display: flex;
align-items: center;
gap: 22rpx;
&__logo {
width: 76rpx;
height: 76rpx;
border: 4rpx solid #1b61b6;
border-radius: 50%;
display: flex;
align-items: center;
justify-content: center;
color: #1b61b6;
font-size: 38rpx;
font-weight: 700;
overflow: hidden;
image {
width: 100%;
height: 100%;
border-radius: 50%;
}
}
}
.hall-tabs {
display: flex;
height: 110rpx;
padding: 0 22rpx;
background: #fff;
border-bottom: 1rpx solid #e7ebf1;
.hall-tab {
flex: 1;
height: 110rpx;
display: flex;
align-items: center;
justify-content: center;
position: relative;
color: #3a3f49;
font-size: 34rpx;
&--active {
color: #1468e8;
font-weight: 700;
&::after {
content: '';
position: absolute;
bottom: -1rpx;
left: 22%;
right: 22%;
height: 6rpx;
border-radius: 6rpx 6rpx 0 0;
background: #1468e8;
}
}
}
}
.lottery-games {
background: #fff;
white-space: nowrap;
border-bottom: 1rpx solid #edf0f4;
&__inner {
display: inline-flex;
align-items: center;
padding: 28rpx 32rpx;
gap: 18rpx;
}
&__empty {
padding: 34rpx 32rpx;
color: #9aa3b1;
font-size: 26rpx;
}
}
.lottery-game-chip {
height: 68rpx;
display: inline-flex;
align-items: center;
justify-content: center;
gap: 8rpx;
padding: 0 28rpx;
border: 2rpx solid #dce2eb;
border-radius: 40rpx;
color: #343b46;
font-size: 28rpx;
flex-shrink: 0;
&--active {
background: #1468e8;
border-color: #1468e8;
color: #fff;
font-weight: 600;
}
&--all {
background: #f6f8fb;
border-color: transparent;
color: #5f6877;
}
&__icon {
width: 36rpx;
height: 36rpx;
border-radius: 50%;
overflow: hidden;
image {
width: 100%;
height: 100%;
}
}
}
.lottery-disclaimer {
min-height: 76rpx;
display: flex;
align-items: center;
gap: 14rpx;
padding: 0 34rpx;
background: #f5f7fb;
color: #7c8491;
font-size: 27rpx;
&__icon {
display: flex;
align-items: center;
}
}
.latest-section {
padding: 30rpx 24rpx 0;
&__header {
display: flex;
align-items: center;
justify-content: space-between;
padding: 0 12rpx 20rpx;
}
&__title {
font-size: 38rpx;
font-weight: 700;
color: #171b24;
}
&__refresh {
display: flex;
align-items: center;
gap: 14rpx;
color: #6e7787;
font-size: 24rpx;
}
}
.latest-empty {
padding: 90rpx 0;
color: #9ca5b3;
font-size: 28rpx;
text-align: center;
}
.latest-card {
margin-bottom: 22rpx;
padding: 28rpx 26rpx 24rpx;
background: #fff;
border: 1rpx solid #dfe5ee;
border-radius: 24rpx;
box-shadow: 0 6rpx 24rpx rgba(34, 64, 106, 0.06);
&__body {
display: flex;
align-items: stretch;
}
&__main {
min-width: 0;
flex: 1;
padding-right: 24rpx;
}
&__identity {
display: flex;
align-items: center;
gap: 20rpx;
}
&__logo {
width: 82rpx;
height: 82rpx;
border-radius: 50%;
border: 2rpx solid #b6cdef;
background: #f6f9ff;
display: flex;
align-items: center;
justify-content: center;
flex-shrink: 0;
overflow: hidden;
image {
width: 100%;
height: 100%;
}
text {
color: #1468e8;
font-size: 30rpx;
font-weight: 700;
}
}
&__meta {
display: flex;
flex-direction: column;
gap: 8rpx;
min-width: 0;
}
&__name {
font-size: 32rpx;
font-weight: 700;
color: #161b24;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
&__issue-row {
display: flex;
align-items: center;
gap: 14rpx;
color: #414957;
font-size: 25rpx;
}
&__status {
padding: 2rpx 10rpx;
border: 2rpx solid #1468e8;
border-radius: 10rpx;
color: #1468e8;
line-height: 1.25;
}
&__date {
color: #626b79;
font-size: 24rpx;
}
&__balls {
display: flex;
align-items: flex-start;
gap: 12rpx;
margin-top: 30rpx;
flex-wrap: wrap;
}
&__next {
width: 236rpx;
flex-shrink: 0;
padding-left: 24rpx;
border-left: 1rpx solid #d9e0ea;
display: flex;
flex-direction: column;
align-items: flex-start;
}
&__next-row {
display: flex;
align-items: center;
gap: 8rpx;
color: #343c48;
font-size: 24rpx;
white-space: nowrap;
}
&__next-issue {
color: #343c48;
}
&__next-label {
margin-top: 36rpx;
color: #343c48;
font-size: 24rpx;
}
&__countdown {
margin-top: 12rpx;
color: #1468e8;
font-size: 42rpx;
line-height: 1.05;
font-weight: 600;
letter-spacing: 1rpx;
white-space: nowrap;
}
&__countdown-labels {
width: 100%;
display: flex;
justify-content: space-around;
margin-top: 10rpx;
color: #606a78;
font-size: 22rpx;
}
&__divider {
height: 2rpx;
margin: 26rpx 0 20rpx;
background: #e3e8ef;
}
&__actions {
display: flex;
gap: 18rpx;
}
&__action {
flex: 1;
height: 74rpx;
display: flex;
align-items: center;
justify-content: center;
gap: 12rpx;
border: 2rpx solid #1468e8;
border-radius: 38rpx;
color: #1468e8;
font-size: 28rpx;
}
}
.ball {
width: 64rpx;
height: 64rpx;
border-radius: 50%;
display: flex;
align-items: center;
justify-content: center;
background: #fff;
border: 2rpx solid #1468e8;
&--red { border-color: #f04444; }
&--blue { border-color: #1468e8; }
&--green { border-color: #159447; }
&--orange { border-color: #eda915; }
&--purple { border-color: #7628dd; }
&__num {
color: #171b24;
font-size: 27rpx;
font-weight: 600;
}
}
.ball__plus {
color: #6c7481;
font-size: 30rpx;
height: 64rpx;
display: flex;
align-items: center;
}
.ball-wrap { gap: 4rpx; }
.ball-zodiac { color: #555e6c; font-size: 18rpx; }
</style>