no message

This commit is contained in:
hajimi
2026-06-11 12:15:29 +08:00
parent 10ebe39c30
commit 96efa1d905
5859 changed files with 815501 additions and 5 deletions
@@ -0,0 +1,591 @@
<template>
<view class="mc" :class="'mc--' + cardType">
<!-- 顶部赛事标签行 -->
<view class="mc__tags">
<view class="mc__tags-left">
<text class="mc__tag-label">{{ match.league_name || '赛事' }}</text>
<view class="mc__tag-pill">
<text>联赛</text>
</view>
<view v-if="match.round_name" class="mc__tag-pill">
<text>{{ match.round_name }}</text>
</view>
</view>
<view class="mc__tags-right">
<text
v-if="showTagTime"
class="mc__time"
:class="'mc__time--' + cardType"
>
{{ scheduleTime }}
</text>
<view v-if="match.is_hot" class="mc__tag-hot">
<text>热门</text>
</view>
</view>
</view>
<!-- 中间主客队 + 比分 -->
<view v-if="match.status === 1" class="mc__body-live" :style="liveStyle">
<view class="mc__bg-left"></view>
<view class="mc__bg-right"></view>
<view class="mc__home mc__home--live">
<image v-if="match.home_icon" class="mc__icon" :src="match.home_icon" mode="aspectFit" />
<text class="mc__name mc__name--white">{{ match.home_team }}</text>
<text class="mc__eng mc__eng--white">{{ match.home_team_en || '' }}</text>
</view>
<view class="mc__vs-area mc__vs-area--live">
<text class="mc__num mc__num--white">{{ match.home_score ?? 0 }}</text>
<text class="mc__vs-text mc__vs-text--live">VS</text>
<text class="mc__num mc__num--white">{{ match.away_score ?? 0 }}</text>
</view>
<view class="mc__away mc__away--live">
<image v-if="match.away_icon" class="mc__icon" :src="match.away_icon" mode="aspectFit" />
<text class="mc__name mc__name--white">{{ match.away_team }}</text>
<text class="mc__eng mc__eng--white">{{ match.away_team_en || '' }}</text>
</view>
</view>
<view v-else-if="match.status === 0" class="mc__body-upcoming">
<view class="mc__row">
<view class="mc__team-row">
<image v-if="match.home_icon" class="mc__icon-sm" :src="match.home_icon" mode="aspectFit" />
<view class="mc__team-info">
<text class="mc__tname">{{ match.home_team }}</text>
<text class="mc__teng">{{ match.home_team_en || '' }}</text>
</view>
</view>
<view class="mc__odds-item">
<text class="mc__odds-label">主胜</text>
<text class="mc__odds-val">{{ match.home_odds || '0.00' }}</text>
</view>
</view>
<view class="mc__row mc__row--mid">
<view class="mc__vs-center">
<text class="mc__vs-text">VS</text>
</view>
<view class="mc__odds-item">
<text class="mc__odds-label">平局</text>
<text class="mc__odds-val">{{ match.draw_odds || '0.00' }}</text>
</view>
</view>
<view class="mc__row">
<view class="mc__team-row mc__team-row--away">
<image v-if="match.away_icon" class="mc__icon-sm" :src="match.away_icon" mode="aspectFit" />
<view class="mc__team-info">
<text class="mc__tname">{{ match.away_team }}</text>
<text class="mc__teng">{{ match.away_team_en || '' }}</text>
</view>
</view>
<view class="mc__odds-item">
<text class="mc__odds-label">客胜</text>
<text class="mc__odds-val">{{ match.away_odds || '0.00' }}</text>
</view>
</view>
</view>
<view v-else class="mc__body">
<view class="mc__home">
<image v-if="match.home_icon" class="mc__icon" :src="match.home_icon" mode="aspectFit" />
<text class="mc__name">{{ match.home_team }}</text>
<text class="mc__eng">{{ match.home_team_en || '' }}</text>
</view>
<view class="mc__vs-area">
<text class="mc__num">{{ match.home_score ?? 0 }}</text>
<text class="mc__vs-text">VS</text>
<text class="mc__num">{{ match.away_score ?? 0 }}</text>
</view>
<view class="mc__away">
<image v-if="match.away_icon" class="mc__icon" :src="match.away_icon" mode="aspectFit" />
<text class="mc__name">{{ match.away_team }}</text>
<text class="mc__eng">{{ match.away_team_en || '' }}</text>
</view>
</view>
<!-- 底部状态 + 时间 -->
<view class="mc__footer" :class="{ 'mc__footer--live-ai': canShowLiveAi }">
<view class="mc__badge" :class="'mc__badge--' + cardType">
<text>{{ statusLabel }}</text>
</view>
<text v-if="showFooterTime" class="mc__time" :class="'mc__time--' + cardType">{{ scheduleTime }}</text>
<view v-if="canShowLiveAi" class="mc__ai-entry" @tap.stop="goAiAnalysis">
<text class="mc__ai-entry-badge">AI</text>
<text class="mc__ai-entry-text">分析</text>
</view>
</view>
</view>
</template>
<script lang="ts" setup>
import { computed } from 'vue'
const props = defineProps<{
match: any
showLiveAi?: boolean
}>()
const statusTypeMap: Record<number, string> = { 1: 'live', 0: 'upcoming', 3: 'postponed', 2: 'ended' }
const statusTextMap: Record<number, string> = { 1: '进行中', 0: '未开始', 3: '推迟', 2: '已结束' }
const sportColors: Record<number, { left: string; right: string }> = {
1: { left: '#008248', right: '#00471b' },
2: { left: '#006BB7', right: '#D0202D' },
4: { left: '#6B3FA0', right: '#3F1D6B' },
5: { left: '#C47A20', right: '#8B5512' }
}
const defaultSportColor = { left: '#008248', right: '#00471b' }
const liveStyle = computed(() => {
const c = sportColors[props.match.sport_type] || defaultSportColor
return {
'--bg-left-color': c.left,
'--bg-right-color': c.right
}
})
const cardType = computed(() => statusTypeMap[props.match.status] || 'other')
const canShowLiveAi = computed(() => {
return !!props.showLiveAi && ['live', 'upcoming'].includes(cardType.value) && !!props.match?.id
})
const showTagTime = computed(() => {
return ['live', 'upcoming', 'ended'].includes(cardType.value)
})
const showFooterTime = computed(() => {
return !showTagTime.value
})
const statusLabel = computed(() => {
if (props.match.status === 1) return '· 进行中 ·'
return statusTextMap[props.match.status] || '未开始'
})
const scheduleTime = computed(() => {
if (!props.match.match_time) return ''
const d = new Date(props.match.match_time * 1000)
const year = d.getFullYear()
const month = String(d.getMonth() + 1).padStart(2, '0')
const date = String(d.getDate()).padStart(2, '0')
const hours = String(d.getHours()).padStart(2, '0')
const minutes = String(d.getMinutes()).padStart(2, '0')
return `${year}-${month}-${date} ${hours}:${minutes}`
})
const goAiAnalysis = () => {
const id = props.match?.id
if (!id) return
uni.navigateTo({ url: `/pages/ai_analysis/ai_analysis?type=match&id=${id}` })
}
</script>
<style lang="scss" scoped>
.mc {
padding: 20rpx 26rpx 10rpx;
background: #fff;
border-radius: 24rpx;
display: flex;
flex-direction: column;
align-items: center;
gap: 10rpx;
&--ended {
background: #f3f4f6;
}
&__tags {
display: flex;
align-items: center;
justify-content: space-between;
width: 100%;
}
&__tags-left {
display: flex;
align-items: center;
gap: 12rpx;
}
&__tags-right {
display: flex;
align-items: center;
gap: 10rpx;
justify-content: flex-end;
margin-left: 12rpx;
}
&__tag-label {
font-size: 24rpx;
color: #808080;
line-height: 1.4;
}
&__tag-pill {
display: flex;
align-items: center;
justify-content: center;
padding: 4rpx 8rpx;
background: #e5edff;
border-radius: 6rpx;
text {
font-size: 20rpx;
color: #185dff;
line-height: 1.4;
}
}
&__tag-hot {
display: flex;
align-items: center;
justify-content: center;
padding: 4rpx 8rpx;
background: #ffe5e5;
border-radius: 6rpx;
text {
font-size: 20rpx;
color: #ee3835;
line-height: 1.4;
}
}
&__body-upcoming {
display: flex;
flex-direction: column;
gap: 6rpx;
width: 100%;
}
&__row {
display: flex;
align-items: center;
justify-content: space-between;
width: 100%;
&--mid {
padding-left: 56rpx;
}
}
&__team-row {
display: flex;
align-items: center;
gap: 8rpx;
}
&__team-info {
display: flex;
align-items: baseline;
gap: 8rpx;
}
&__icon-sm {
width: 48rpx;
height: 48rpx;
flex-shrink: 0;
}
&__tname {
font-size: 28rpx;
font-weight: 500;
color: #000;
line-height: 1.4;
}
&__teng {
font-size: 24rpx;
color: #000;
line-height: 1.4;
text-transform: capitalize;
}
&__vs-center {
display: flex;
align-items: center;
}
&__odds-item {
display: flex;
align-items: baseline;
gap: 4rpx;
}
&__odds-label {
font-size: 24rpx;
color: #808080;
line-height: 1.4;
}
&__odds-val {
font-size: 28rpx;
font-weight: 500;
color: #185dff;
line-height: 1.4;
width: 64rpx;
text-align: right;
}
&__body {
display: flex;
align-items: flex-start;
justify-content: space-between;
width: 100%;
}
&__body-live {
position: relative;
display: flex;
align-items: flex-start;
justify-content: space-between;
width: 100%;
overflow: hidden;
border-radius: 24rpx;
}
&__bg-left {
position: absolute;
top: 0;
left: -8%;
width: 56%;
height: 100%;
background: var(--bg-left-color, #008248);
transform: skewX(-35deg);
z-index: 0;
}
&__bg-right {
position: absolute;
top: 0;
right: -8%;
width: 56%;
height: 100%;
background: var(--bg-right-color, #00471b);
transform: skewX(-35deg);
z-index: 0;
}
&__home {
position: relative;
z-index: 1;
flex: 1;
display: flex;
flex-direction: column;
gap: 4rpx;
min-width: 0;
&--live {
padding: 20rpx 0 20rpx 40rpx;
}
}
&__away {
position: relative;
z-index: 1;
flex: 1;
display: flex;
flex-direction: column;
align-items: flex-end;
gap: 4rpx;
min-width: 0;
&--live {
padding: 20rpx 40rpx 20rpx 0;
}
}
&__icon {
width: 64rpx;
height: 64rpx;
flex-shrink: 0;
}
&__name {
font-size: 32rpx;
font-weight: 500;
color: #000;
line-height: 1.4;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
max-width: 100%;
&--white {
color: #fff;
}
}
&__eng {
font-size: 24rpx;
color: #000;
line-height: 1.4;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
max-width: 100%;
&--white {
color: #fff;
}
}
&__vs-area {
position: relative;
z-index: 1;
display: flex;
align-items: center;
gap: 32rpx;
padding: 0 24rpx;
flex-shrink: 0;
align-self: center;
&--live {
padding: 0 24rpx;
}
}
&__num {
font-size: 36rpx;
font-weight: 600;
color: #000;
line-height: 1.4;
&--white {
color: #fff;
}
}
&__vs-text {
font-size: 24rpx;
font-weight: 600;
color: #808080;
line-height: 1.4;
&--live {
color: #fff;
text-shadow: 0 4rpx 6rpx rgba(0, 0, 0, 0.25);
-webkit-text-stroke: 2rpx #ee3835;
paint-order: stroke fill;
background: linear-gradient(180deg, #ee3835 0%, #185dff 100%);
-webkit-background-clip: text;
background-clip: text;
-webkit-text-stroke-color: transparent;
}
}
&__footer {
display: flex;
flex-direction: column;
align-items: center;
gap: 16rpx;
&--live-ai {
width: 100%;
flex-direction: row;
align-items: center;
justify-content: space-between;
gap: 20rpx;
}
}
&__ai-entry {
display: flex;
align-items: center;
justify-content: center;
gap: 6rpx;
min-width: 152rpx;
padding: 6rpx 14rpx;
border-radius: 999rpx;
background: #f4f7ff;
&-badge {
min-width: 40rpx;
height: 40rpx;
padding: 0 10rpx;
border-radius: 999rpx;
background: linear-gradient(135deg, #185dff 0%, #4f7dff 100%);
font-size: 22rpx;
font-weight: 700;
color: #fff;
line-height: 40rpx;
text-align: center;
}
&-text {
font-size: 24rpx;
font-weight: 600;
color: #185dff;
line-height: 1.2;
}
}
&__badge {
display: flex;
align-items: center;
padding: 8rpx 32rpx;
border-radius: 24rpx;
text {
font-size: 24rpx;
font-weight: 500;
line-height: 1.4;
}
&--upcoming {
background: #e5edff;
text {
color: #185dff;
}
}
&--live {
background: #185dff;
text {
color: #fff;
}
}
&--ended {
background: #808080;
text {
color: #fff;
}
}
&--postponed {
background: #fff1dd;
text {
color: #ff9900;
}
}
&--other {
background: #f0f0f0;
text {
color: #666;
}
}
}
&__time {
font-size: 24rpx;
color: #808080;
line-height: 1.4;
text-align: center;
&--live {
color: #185dff;
}
&--upcoming {
color: #185dff;
}
&--ended {
color: #6b7280;
}
}
}
</style>