style: unify lottery history page

This commit is contained in:
hajimi
2026-08-03 16:11:06 +08:00
parent 81fb424ddf
commit acc994d16c
2 changed files with 295 additions and 36 deletions
+14
View File
@@ -13,6 +13,20 @@
## 一、已完成事项 ## 一、已完成事项
### 127. 历史开奖记录页主页风格统一
- 状态:代码已完成,待 H5 验收 - 时间:2026-08-03
完成内容:
- 历史开奖页统一彩票主页的 SB 品牌导航、蓝色主色和浅灰背景层级。
- 开奖记录改为带彩种标识、状态标签、号码球和操作按钮的卡片布局。
- 增加记录总数、数据说明及详情/智能分析入口,保持原分页和 AI 功能不变。
涉及模块:
- `uniapp/src/packages_lottery/pages/draw_list.vue`
### 126. 历史开奖记录页面数据兼容优化 ### 126. 历史开奖记录页面数据兼容优化
- 状态:代码已完成,待 H5 验收 - 时间:2026-08-03 - 状态:代码已完成,待 H5 验收 - 时间:2026-08-03
+281 -36
View File
@@ -1,17 +1,34 @@
<template> <template>
<page-meta :page-style="showAiPopup ? 'overflow: hidden;' : ''" /> <page-meta :page-style="showAiPopup ? 'overflow: hidden;' : ''" />
<view class="draw-list-page" :class="{ 'page-no-scroll': showAiPopup }"> <view class="draw-list-page" :class="{ 'page-no-scroll': showAiPopup }">
<!-- 导航 --> <!-- 与彩票主页统一的品牌导航 -->
<view class="dl-nav" :style="{ paddingTop: statusBarHeight + 'px' }"> <view class="dl-nav" :style="{ paddingTop: statusBarHeight + 'px' }">
<view class="dl-nav__content"> <view class="dl-nav__content">
<view class="dl-nav__back" @tap="goBack"> <view class="dl-nav__back" @tap="goBack">
<u-icon name="arrow-left" size="36" color="#fff" /> <u-icon name="arrow-left" size="34" color="#1f2937" />
</view>
<view class="dl-nav__brand">
<image v-if="websiteLogo" class="dl-nav__logo" :src="websiteLogo" mode="aspectFit" />
<view v-else class="dl-nav__logo dl-nav__logo--fallback"><text>SB</text></view>
<view class="dl-nav__titles">
<text class="dl-nav__title">历史开奖</text>
<text class="dl-nav__subtitle">{{ categoryName }}</text>
</view>
</view>
<view class="dl-nav__action" @tap="goBack">
<text>彩票中心</text>
</view> </view>
<text class="dl-nav__title">{{ categoryName }}</text>
<view class="dl-nav__placeholder" />
</view> </view>
</view> </view>
<view class="draw-list__intro">
<view>
<text class="draw-list__intro-title">{{ categoryName }}开奖记录</text>
<text class="draw-list__intro-desc">按开奖时间倒序排列数据仅供参考</text>
</view>
<text v-if="totalCount" class="draw-list__intro-count"> {{ totalCount }} </text>
</view>
<!-- 开奖列表 --> <!-- 开奖列表 -->
<z-paging ref="paging" v-model="drawList" @query="queryList" :fixed="false" height="calc(100vh - 44px)"> <z-paging ref="paging" v-model="drawList" @query="queryList" :fixed="false" height="calc(100vh - 44px)">
<view v-if="!drawList.length && !listLoading" class="draw-list__empty"> <view v-if="!drawList.length && !listLoading" class="draw-list__empty">
@@ -24,10 +41,21 @@
</view> </view>
<view v-for="item in drawList" :key="item.code + item.issue" class="draw-card"> <view v-for="item in drawList" :key="item.code + item.issue" class="draw-card">
<view class="draw-card__header"> <view class="draw-card__header">
<text class="draw-card__period"> {{ item.issue }} </text> <view class="draw-card__game">
<text class="draw-card__date">{{ item.draw_time }}</text> <view class="draw-card__logo"><text>{{ categoryName.slice(0, 1) }}</text></view>
<view class="draw-card__badge" :class="{ 'draw-card__badge--pending': Number(item.status) !== 1 }"> <view class="draw-card__meta">
<text>{{ Number(item.status) === 1 ? '已开奖' : '待开奖' }}</text> <text class="draw-card__name">{{ categoryName }}</text>
<view class="draw-card__period-row">
<text class="draw-card__period"> {{ item.issue }} </text>
<view class="draw-card__badge" :class="{ 'draw-card__badge--pending': Number(item.status) !== 1 }">
<text>{{ Number(item.status) === 1 ? '已开奖' : '待开奖' }}</text>
</view>
</view>
</view>
</view>
<view class="draw-card__date-wrap">
<text class="draw-card__date">{{ item.draw_time }}</text>
<text class="draw-card__arrow"></text>
</view> </view>
</view> </view>
<view v-if="Number(item.status) === 1 && item.numbers?.length" class="draw-card__balls"> <view v-if="Number(item.status) === 1 && item.numbers?.length" class="draw-card__balls">
@@ -51,6 +79,16 @@
<text class="ai-predict-btn__arrow"></text> <text class="ai-predict-btn__arrow"></text>
</view> </view>
</view> </view>
<view v-if="Number(item.status) === 1" class="draw-card__actions">
<view class="draw-card__action" @tap.stop="goDetail(item)">
<u-icon name="file-text" size="28" color="#185dff" />
<text>查看详情</text>
</view>
<view class="draw-card__action" @tap.stop="openAiPopup(item)">
<text class="draw-card__action-ai">AI</text>
<text>智能分析</text>
</view>
</view>
</view> </view>
</z-paging> </z-paging>
@@ -153,6 +191,7 @@ import { ref, shallowRef, computed } from 'vue'
import { onLoad } from '@dcloudio/uni-app' import { onLoad } from '@dcloudio/uni-app'
import { getDrawResultList, getLatestDrawResult, getLotteryAiPredict } from '@/api/lottery' import { getDrawResultList, getLatestDrawResult, getLotteryAiPredict } from '@/api/lottery'
import { useUserStore } from '@/stores/user' import { useUserStore } from '@/stores/user'
import { useAppStore } from '@/stores/app'
import { AI_DAILY_FREE_TEXT, getAiFreeRemain } from '@/config/ai' import { AI_DAILY_FREE_TEXT, getAiFreeRemain } from '@/config/ai'
const statusBarHeight = ref(0) const statusBarHeight = ref(0)
@@ -161,9 +200,12 @@ const gameTemplate = ref('')
const categoryName = ref('') const categoryName = ref('')
const drawList = ref<any[]>([]) const drawList = ref<any[]>([])
const latestDraw = ref<any>(null) const latestDraw = ref<any>(null)
const totalCount = ref(0)
const listLoading = ref(false) const listLoading = ref(false)
const listError = ref(false) const listError = ref(false)
const paging = shallowRef() const paging = shallowRef()
const appStore = useAppStore()
const websiteLogo = computed(() => appStore.getWebsiteConfig.shop_logo || '')
uni.getSystemInfo({ uni.getSystemInfo({
success: (res) => { success: (res) => {
@@ -231,6 +273,7 @@ const queryList = async (pageNo: number, pageSize: number) => {
? item.numbers ? item.numbers
: String(item.draw_code || '').split(',').filter(Boolean) : String(item.draw_code || '').split(',').filter(Boolean)
})) }))
totalCount.value = Number(res?.count ?? res?.data?.count ?? totalCount.value) || 0
lists.forEach((item: any) => { item.game_name = categoryName.value }) lists.forEach((item: any) => { item.game_name = categoryName.value })
paging.value?.complete(lists) paging.value?.complete(lists)
} catch (e) { } catch (e) {
@@ -370,87 +413,267 @@ onLoad((options: any) => {
} }
.dl-nav { .dl-nav {
background: linear-gradient(135deg, #185dff, #ff6b6b); background: #fff;
border-bottom: 1rpx solid #edf0f5;
&__content { &__content {
height: 44px; min-height: 66px;
display: flex; display: flex;
align-items: center; align-items: center;
padding: 0 24rpx; padding: 0 24rpx;
} }
&__back { &__back {
width: 60rpx; width: 64rpx;
height: 44px; height: 64rpx;
display: flex; display: flex;
align-items: center; align-items: center;
} }
&__title { &__brand {
display: flex;
align-items: center;
gap: 16rpx;
flex: 1; flex: 1;
text-align: center; min-width: 0;
font-size: 34rpx;
font-weight: bold;
color: #fff;
} }
&__placeholder { &__logo {
width: 60rpx; width: 68rpx;
height: 68rpx;
border-radius: 50%;
flex-shrink: 0;
}
&__logo--fallback {
display: flex;
align-items: center;
justify-content: center;
background: #185dff;
border: 4rpx solid #dce8ff;
text {
color: #fff;
font-size: 23rpx;
font-style: italic;
font-weight: 900;
}
}
&__titles {
display: flex;
flex-direction: column;
gap: 2rpx;
min-width: 0;
}
&__title {
font-size: 36rpx;
font-weight: bold;
color: #111827;
line-height: 1.1;
}
&__subtitle {
max-width: 400rpx;
overflow: hidden;
color: #8b95a7;
font-size: 22rpx;
text-overflow: ellipsis;
white-space: nowrap;
}
&__action {
padding: 12rpx 18rpx;
border-radius: 24rpx;
background: #eef4ff;
color: #185dff;
font-size: 22rpx;
white-space: nowrap;
} }
} }
.draw-list__intro {
display: flex;
align-items: center;
justify-content: space-between;
padding: 26rpx 30rpx 20rpx;
background: #f5f7fb;
}
.draw-list__intro-title {
display: block;
color: #111827;
font-size: 32rpx;
font-weight: 700;
}
.draw-list__intro-desc {
display: block;
margin-top: 6rpx;
color: #9aa3b2;
font-size: 22rpx;
}
.draw-list__intro-count {
color: #185dff;
font-size: 22rpx;
white-space: nowrap;
}
.draw-card { .draw-card {
margin: 20rpx 24rpx 0; margin: 16rpx 24rpx 0;
background: #fff; background: #fff;
border-radius: 16rpx; border: 1rpx solid #dfe5ee;
padding: 24rpx; border-radius: 18rpx;
padding: 22rpx 22rpx 18rpx;
box-shadow: 0 4rpx 14rpx rgba(28, 53, 89, 0.03);
&__header { &__header {
display: flex;
align-items: center;
justify-content: space-between;
margin-bottom: 18rpx;
}
&__game {
display: flex;
align-items: center;
gap: 14rpx;
min-width: 0;
}
&__logo {
width: 64rpx;
height: 64rpx;
display: flex;
align-items: center;
justify-content: center;
flex-shrink: 0;
border: 2rpx solid #ff6a55;
border-radius: 50%;
background: linear-gradient(145deg, #ff8b6e, #ee3835);
text {
color: #fff;
font-size: 25rpx;
font-weight: 700;
}
}
&__meta {
display: flex;
flex-direction: column;
gap: 6rpx;
min-width: 0;
}
&__name {
overflow: hidden;
color: #111827;
font-size: 29rpx;
font-weight: 700;
text-overflow: ellipsis;
white-space: nowrap;
}
&__period-row {
display: flex; display: flex;
align-items: center; align-items: center;
gap: 12rpx; gap: 12rpx;
margin-bottom: 20rpx; }
&__date-wrap {
display: flex;
align-items: center;
gap: 6rpx;
flex-shrink: 0;
margin-left: 12rpx;
} }
&__period { &__period {
font-size: 28rpx; font-size: 30rpx;
font-weight: bold; font-weight: bold;
color: #222; color: #222;
} }
&__date { &__date {
font-size: 24rpx; font-size: 22rpx;
color: #999; color: #8b95a7;
margin-left: auto; }
&__arrow {
color: #8b95a7;
font-size: 36rpx;
line-height: 1;
} }
&__badge { &__badge {
font-size: 22rpx; font-size: 20rpx;
color: #22c55e; color: #185dff;
background: #f0fdf4; background: #eef4ff;
padding: 4rpx 16rpx; padding: 5rpx 14rpx;
border-radius: 8rpx; border-radius: 18rpx;
&--pending { &--pending {
color: #f59e0b; color: #f59e0b;
background: #fffbeb; background: #fff8e8;
} }
} }
&__balls { &__balls {
display: flex; display: flex;
align-items: center; align-items: center;
gap: 10rpx; gap: 14rpx;
flex-wrap: wrap; flex-wrap: wrap;
margin-bottom: 16rpx; margin: 6rpx 0 18rpx;
} }
&__pending { &__pending {
text-align: center; text-align: center;
padding: 20rpx; padding: 22rpx;
color: #999; color: #999;
font-size: 26rpx; font-size: 26rpx;
} }
&__actions {
display: flex;
gap: 12rpx;
padding-top: 16rpx;
border-top: 1rpx solid #edf0f5;
}
&__action {
flex: 1;
height: 66rpx;
display: flex;
align-items: center;
justify-content: center;
gap: 8rpx;
border: 2rpx solid #185dff;
border-radius: 14rpx;
color: #185dff;
font-size: 26rpx;
&:active {
background: #f0f5ff;
}
}
&__action-ai {
display: inline-flex;
align-items: center;
justify-content: center;
min-width: 34rpx;
height: 28rpx;
padding: 0 5rpx;
border-radius: 6rpx;
background: #185dff;
color: #fff;
font-size: 17rpx;
font-weight: 800;
letter-spacing: 1rpx;
}
} }
/* 号码球 */ /* 号码球 */
@@ -500,6 +723,28 @@ onLoad((options: any) => {
font-size: 22rpx; font-size: 22rpx;
} }
.draw-card .ball--sm {
background: #fff;
border: 2rpx solid #185dff;
box-shadow: none;
}
.draw-card .ball--red {
border-color: #ff3b30;
}
.draw-card .ball--green {
border-color: #19a957;
}
.draw-card .ball--blue {
border-color: #185dff;
}
.draw-card .ball__num {
color: #111827;
}
/* 球+生肖容器 */ /* 球+生肖容器 */
.ball-wrap { .ball-wrap {
display: flex; display: flex;