818 lines
22 KiB
Vue
818 lines
22 KiB
Vue
<template>
|
||
<div class="number-generator">
|
||
<div class="header">
|
||
<h1>一键下单·拼盘早点</h1>
|
||
<p class="subtitle">今日拼盘新鲜出锅,懒人专属,AI大厨为你配号!</p>
|
||
</div>
|
||
|
||
<!-- 定时任务状态区域 -->
|
||
<div class="scheduler-status-section">
|
||
<div class="status-card">
|
||
<div class="status-header">
|
||
<h3>定时任务状态</h3>
|
||
<el-button type="primary" size="small" @click="updateSchedulerStatus">刷新状态</el-button>
|
||
</div>
|
||
<div class="status-content">
|
||
<div class="status-item">
|
||
<span class="status-label">数据更新任务:</span>
|
||
<span class="status-value">
|
||
<el-tag type="success" size="small">每天早上6点</el-tag>
|
||
</span>
|
||
<span class="status-time">
|
||
下次更新:{{ schedulerStatus.nextUpdate ? new Date(schedulerStatus.nextUpdate).toLocaleString() : '未知' }}
|
||
</span>
|
||
</div>
|
||
<div class="status-item">
|
||
<span class="status-label">拼盘推荐任务:</span>
|
||
<span class="status-value">
|
||
<el-tag type="warning" size="small">每天下午5点</el-tag>
|
||
</span>
|
||
<span class="status-time">
|
||
下次推荐:{{ schedulerStatus.nextRecommend ? new Date(schedulerStatus.nextRecommend).toLocaleString() : '未知' }}
|
||
</span>
|
||
</div>
|
||
<div class="status-item">
|
||
<span class="status-label">今日推荐状态:</span>
|
||
<span class="status-value">
|
||
<el-tag v-if="todayRecommend.length > 0" type="success" size="small">已生成 {{ todayRecommend.length }} 注</el-tag>
|
||
<el-tag v-else type="info" size="small">等待生成</el-tag>
|
||
</span>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- 一键下单区域 -->
|
||
<div class="quick-order-section">
|
||
<div class="order-card">
|
||
<div class="card-header">
|
||
<h3>今日拼盘</h3>
|
||
<span class="lottery-type" :class="{ active: currentLotteryType === 'ssq' }">{{ currentLotteryType === 'ssq' ? '双色球' : '大乐透' }}</span>
|
||
</div>
|
||
<div class="order-content">
|
||
<div class="order-info">
|
||
<p class="order-time">下单时间:{{ todayRecommend.length ? todayRecommend[0].time : '还没开锅,快来点一份吧~' }}</p>
|
||
<p class="order-batch">拼盘编号:{{ todayRecommend.length ? todayRecommend[0].batch_id : '暂无,先点单再说~' }}</p>
|
||
</div>
|
||
<div class="order-numbers" v-if="todayRecommend.length">
|
||
<div v-for="(order, idx) in todayRecommend" :key="order.id" class="number-display multi">
|
||
<span class="order-index">{{ idx + 1 }}</span>
|
||
<span class="red-balls">
|
||
<span v-for="num in order.redNumbers" :key="num" class="ball red">{{ num.toString().padStart(2, '0') }}</span>
|
||
</span>
|
||
<span class="separator">|</span>
|
||
<span class="blue-balls">
|
||
<span v-for="num in order.blueNumbers" :key="num" class="ball blue">{{ num.toString().padStart(2, '0') }}</span>
|
||
</span>
|
||
<span class="recommend-type">{{ order.recommend_type }}</span>
|
||
</div>
|
||
</div>
|
||
<div class="no-order" v-else>
|
||
<p>今日拼盘还没出锅,快点下方按钮,开启你的好运早餐!</p>
|
||
</div>
|
||
</div>
|
||
<div class="order-actions">
|
||
<button
|
||
@click="generateNumbers"
|
||
:disabled="loading"
|
||
class="generate-btn"
|
||
>
|
||
<span v-if="loading">大厨配号中...</span>
|
||
<span v-else>来一份拼盘</span>
|
||
</button>
|
||
<button
|
||
@click="copyAllNumbers"
|
||
:disabled="loading"
|
||
class="copy-all-btn"
|
||
>
|
||
<span v-if="loading">打包中...</span>
|
||
<span v-else>打包带走</span>
|
||
</button>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- 投注历史 -->
|
||
<div class="history-section">
|
||
<div class="history-header">
|
||
<h3>拼盘出锅记录</h3>
|
||
<div class="history-tabs">
|
||
<button :class="{ active: activeTab === 'ssq' }" class="tab-btn" @click="activeTab = 'ssq'">红蓝球煎饼</button>
|
||
<button :class="{ active: activeTab === 'dlt' }" class="tab-btn" @click="activeTab = 'dlt'">大乐透豆浆</button>
|
||
</div>
|
||
<button class="check-win-btn" @click="handleCheckWin" :disabled="checkingWin">
|
||
<span v-if="checkingWin">加料验收中...</span>
|
||
<span v-else>手动加料验收</span>
|
||
</button>
|
||
</div>
|
||
<div class="history-content">
|
||
<div v-if="activeTab === 'ssq'" class="tab-content">
|
||
<div v-for="(group, gIdx) in ssqHistoryGroups" :key="gIdx" class="history-group">
|
||
<div class="group-header">
|
||
<span class="batch-id">拼盘编号:{{ group[0].batch_id }}</span>
|
||
<span class="issue">出锅期号:{{ group[0].issue }}</span>
|
||
<span class="create-time">出锅时间:{{ formatDate(group[0].created_at) }}</span>
|
||
</div>
|
||
<div class="group-numbers">
|
||
<div v-for="record in group" :key="record.id" class="group-number-item" :class="{ win: record.is_winner }">
|
||
<span class="red-balls">
|
||
<span v-for="num in record.redNumbers" :key="num" class="ball red">{{ num.toString().padStart(2, '0') }}</span>
|
||
</span>
|
||
<span class="separator">|</span>
|
||
<span class="blue-balls">
|
||
<span v-for="num in record.blueNumbers" :key="num" class="ball blue">{{ num.toString().padStart(2, '0') }}</span>
|
||
</span>
|
||
<span class="recommend-type">{{ beautifyRecommendType(record.recommend_type) }}</span>
|
||
<span v-if="record.is_winner" class="win-info">
|
||
<span class="win-level">加料成功!恭喜发财!</span>
|
||
<span class="win-amount">收获奖金:{{ record.win_amount }}元</span>
|
||
</span>
|
||
<span v-else class="not-win">未加料成功</span>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<div v-if="activeTab === 'dlt'" class="tab-content">
|
||
<div v-for="(group, gIdx) in dltHistoryGroups" :key="gIdx" class="history-group">
|
||
<div class="group-header">
|
||
<span class="batch-id">拼盘编号:{{ group[0].batch_id }}</span>
|
||
<span class="issue">出锅期号:{{ group[0].issue }}</span>
|
||
<span class="create-time">出锅时间:{{ formatDate(group[0].created_at) }}</span>
|
||
</div>
|
||
<div class="group-numbers">
|
||
<div v-for="record in group" :key="record.id" class="group-number-item" :class="{ win: record.is_winner }">
|
||
<span class="red-balls">
|
||
<span v-for="num in record.redNumbers" :key="num" class="ball red">{{ num.toString().padStart(2, '0') }}</span>
|
||
</span>
|
||
<span class="separator">|</span>
|
||
<span class="blue-balls">
|
||
<span v-for="num in record.blueNumbers" :key="num" class="ball blue">{{ num.toString().padStart(2, '0') }}</span>
|
||
</span>
|
||
<span class="recommend-type">{{ beautifyRecommendType(record.recommend_type) }}</span>
|
||
<span v-if="record.is_winner" class="win-info">
|
||
<span class="win-level">加料成功!恭喜发财!</span>
|
||
<span class="win-amount">收获奖金:{{ record.win_amount }}元</span>
|
||
</span>
|
||
<span v-else class="not-win">未加料成功</span>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</template>
|
||
|
||
<script>
|
||
import { recommendToday, getTodayRecommendations } from '@/api/prediction'
|
||
import { lotteryApi } from '@/api/lottery'
|
||
|
||
export default {
|
||
name: 'NumberGenerator',
|
||
data() {
|
||
return {
|
||
loading: false,
|
||
activeTab: 'ssq',
|
||
currentLotteryType: 'ssq',
|
||
todayRecommend: [],
|
||
ssqHistory: [],
|
||
dltHistory: [],
|
||
checkingWin: false,
|
||
schedulerStatus: {
|
||
nextUpdate: null,
|
||
nextRecommend: null
|
||
}
|
||
}
|
||
},
|
||
computed: {
|
||
ssqHistoryGroups() {
|
||
const groups = []
|
||
for (let i = 0; i < this.ssqHistory.length; i += 4) {
|
||
groups.push(this.ssqHistory.slice(i, i + 4))
|
||
}
|
||
return groups
|
||
},
|
||
dltHistoryGroups() {
|
||
const groups = []
|
||
for (let i = 0; i < this.dltHistory.length; i += 4) {
|
||
groups.push(this.dltHistory.slice(i, i + 4))
|
||
}
|
||
return groups
|
||
}
|
||
},
|
||
mounted() {
|
||
this.loadHistory()
|
||
this.loadTodayRecommendations()
|
||
this.setActiveTabByDay()
|
||
this.updateSchedulerStatus()
|
||
},
|
||
methods: {
|
||
getNext6am() {
|
||
const now = new Date()
|
||
const today6am = new Date(now.getFullYear(), now.getMonth(), now.getDate(), 6, 0, 0)
|
||
if (now < today6am) {
|
||
return today6am
|
||
} else {
|
||
// 明天早上6点
|
||
return new Date(now.getFullYear(), now.getMonth(), now.getDate() + 1, 6, 0, 0)
|
||
}
|
||
},
|
||
getNext5pm() {
|
||
const now = new Date()
|
||
const today5pm = new Date(now.getFullYear(), now.getMonth(), now.getDate(), 17, 0, 0)
|
||
if (now < today5pm) {
|
||
return today5pm
|
||
} else {
|
||
// 明天下午5点
|
||
return new Date(now.getFullYear(), now.getMonth(), now.getDate() + 1, 17, 0, 0)
|
||
}
|
||
},
|
||
updateSchedulerStatus() {
|
||
this.schedulerStatus = {
|
||
nextUpdate: this.getNext6am(),
|
||
nextRecommend: this.getNext5pm(),
|
||
}
|
||
},
|
||
async loadTodayRecommendations() {
|
||
try {
|
||
const response = await getTodayRecommendations()
|
||
if (response.data && response.data.success) {
|
||
this.currentLotteryType = response.data.lottery_type
|
||
this.todayRecommend = response.data.recommend.map(item => {
|
||
const { redNumbers, blueNumbers } = this.parseNumbers(item.numbers)
|
||
return {
|
||
...item,
|
||
redNumbers,
|
||
blueNumbers,
|
||
time: new Date(item.created_at).toLocaleString()
|
||
}
|
||
})
|
||
}
|
||
} catch (error) {
|
||
console.error('加载今日推荐失败:', error)
|
||
}
|
||
},
|
||
async generateNumbers() {
|
||
this.loading = true
|
||
try {
|
||
const response = await recommendToday()
|
||
if (response.data.success) {
|
||
this.currentLotteryType = response.data.lottery_type
|
||
// 解析多注推荐
|
||
this.todayRecommend = (response.data.recommend || []).map(item => {
|
||
const { redNumbers, blueNumbers } = this.parseNumbers(item.numbers)
|
||
return {
|
||
...item,
|
||
redNumbers,
|
||
blueNumbers,
|
||
time: new Date().toLocaleString()
|
||
}
|
||
})
|
||
// 刷新历史记录
|
||
this.loadHistory()
|
||
this.$message.success('拼盘出锅成功,祝你好运连连!')
|
||
}
|
||
} catch (error) {
|
||
console.error('生成号码失败:', error)
|
||
this.$message.error('大厨打盹了,再点一次试试~')
|
||
} finally {
|
||
this.loading = false
|
||
}
|
||
},
|
||
parseNumbers(numbersStr) {
|
||
if (!numbersStr) return { redNumbers: [], blueNumbers: [] }
|
||
const parts = numbersStr.split('|')
|
||
return {
|
||
redNumbers: parts[0] ? parts[0].split(',').map(n => parseInt(n)) : [],
|
||
blueNumbers: parts[1] ? parts[1].split(',').map(n => parseInt(n)) : []
|
||
}
|
||
},
|
||
async loadHistory() {
|
||
try {
|
||
// 加载双色球历史
|
||
const ssqResponse = await lotteryApi.getBetHistory('ssq', { page: 1, size: 20 })
|
||
if (ssqResponse.data.success) {
|
||
this.ssqHistory = ssqResponse.data.records.map(record => ({
|
||
...record,
|
||
...this.parseNumbers(record.numbers)
|
||
}))
|
||
}
|
||
// 加载大乐透历史
|
||
const dltResponse = await lotteryApi.getBetHistory('dlt', { page: 1, size: 20 })
|
||
if (dltResponse.data.success) {
|
||
this.dltHistory = dltResponse.data.records.map(record => ({
|
||
...record,
|
||
...this.parseNumbers(record.numbers)
|
||
}))
|
||
}
|
||
} catch (error) {
|
||
console.error('加载历史记录失败:', error)
|
||
}
|
||
},
|
||
setActiveTabByDay() {
|
||
// 自动根据今天是周几切换tab,1=Monday, 7=Sunday
|
||
const weekday = new Date().getDay() || 7
|
||
if ([1, 3, 6].includes(weekday)) {
|
||
this.activeTab = 'dlt'
|
||
this.currentLotteryType = 'dlt'
|
||
} else {
|
||
this.activeTab = 'ssq'
|
||
this.currentLotteryType = 'ssq'
|
||
}
|
||
},
|
||
formatDate(dateStr) {
|
||
if (!dateStr) return ''
|
||
const date = new Date(dateStr)
|
||
return date.toLocaleString('zh-CN', {
|
||
year: 'numeric',
|
||
month: '2-digit',
|
||
day: '2-digit',
|
||
hour: '2-digit',
|
||
minute: '2-digit'
|
||
})
|
||
},
|
||
async handleCheckWin() {
|
||
this.checkingWin = true
|
||
try {
|
||
const res = await lotteryApi.checkWin(this.activeTab)
|
||
if (res.data && res.data.success) {
|
||
this.$message.success('中奖比对完成!')
|
||
this.loadHistory()
|
||
} else {
|
||
this.$message.error(res.data.message || '比对失败')
|
||
}
|
||
} catch (e) {
|
||
this.$message.error('比对失败')
|
||
} finally {
|
||
this.checkingWin = false
|
||
}
|
||
},
|
||
copyAllNumbers() {
|
||
const lines = this.todayRecommend.map(item => {
|
||
const reds = item.redNumbers.map(n => n.toString().padStart(2, '0')).join(' ')
|
||
const blues = item.blueNumbers.map(n => n.toString().padStart(2, '0')).join(' ')
|
||
return `${reds} | ${blues}`
|
||
})
|
||
const text = lines.join('\n')
|
||
navigator.clipboard.writeText(text)
|
||
.then(() => {
|
||
this.$message.success('号码已打包,快去分享给小伙伴吧!')
|
||
})
|
||
.catch(() => {
|
||
this.$message.error('打包失败,厨房太忙啦~')
|
||
})
|
||
},
|
||
beautifyRecommendType(type) {
|
||
if (!type) return ''
|
||
if (type.includes('热冷')) return 'AI大厨热冷号'
|
||
if (type.includes('模式')) return '灵感模式拼盘'
|
||
if (type.includes('智能选号')) return '智能选号补足'
|
||
return type
|
||
}
|
||
}
|
||
}
|
||
</script>
|
||
|
||
<style scoped>
|
||
.number-generator {
|
||
max-width: 1200px;
|
||
margin: 0 auto;
|
||
padding: 20px;
|
||
}
|
||
|
||
.header {
|
||
text-align: center;
|
||
margin-bottom: 30px;
|
||
}
|
||
|
||
.header h1 {
|
||
color: #2c3e50;
|
||
margin-bottom: 10px;
|
||
font-size: 2.5rem;
|
||
}
|
||
|
||
.subtitle {
|
||
color: #7f8c8d;
|
||
font-size: 1.1rem;
|
||
}
|
||
|
||
.scheduler-status-section {
|
||
margin-bottom: 40px;
|
||
}
|
||
|
||
.status-card {
|
||
background: white;
|
||
border-radius: 16px;
|
||
box-shadow: 0 6px 24px rgba(0, 0, 0, 0.10);
|
||
padding: 36px 36px 28px 36px;
|
||
}
|
||
|
||
.status-header {
|
||
display: flex;
|
||
justify-content: space-between;
|
||
align-items: center;
|
||
margin-bottom: 20px;
|
||
padding-bottom: 15px;
|
||
border-bottom: 2px solid #f8f9fa;
|
||
}
|
||
|
||
.status-header h3 {
|
||
color: #2c3e50;
|
||
margin: 0;
|
||
font-size: 1.5rem;
|
||
}
|
||
|
||
.status-content {
|
||
margin-bottom: 25px;
|
||
}
|
||
|
||
.status-item {
|
||
margin-bottom: 15px;
|
||
}
|
||
|
||
.status-item .status-label {
|
||
color: #7f8c8d;
|
||
font-size: 0.95rem;
|
||
}
|
||
|
||
.status-item .status-value {
|
||
margin-left: 10px;
|
||
font-size: 0.95rem;
|
||
}
|
||
|
||
.status-item .status-time {
|
||
margin-left: 10px;
|
||
font-size: 0.95rem;
|
||
}
|
||
|
||
.quick-order-section {
|
||
margin-bottom: 40px;
|
||
}
|
||
|
||
.order-card {
|
||
background: white;
|
||
border-radius: 16px;
|
||
box-shadow: 0 6px 24px rgba(0, 0, 0, 0.10);
|
||
padding: 36px 36px 28px 36px;
|
||
}
|
||
|
||
.card-header {
|
||
display: flex;
|
||
justify-content: space-between;
|
||
align-items: center;
|
||
margin-bottom: 20px;
|
||
padding-bottom: 15px;
|
||
border-bottom: 2px solid #f8f9fa;
|
||
}
|
||
|
||
.card-header h3 {
|
||
color: #2c3e50;
|
||
margin: 0;
|
||
font-size: 1.5rem;
|
||
}
|
||
|
||
.lottery-type {
|
||
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
|
||
color: white;
|
||
padding: 8px 16px;
|
||
border-radius: 20px;
|
||
font-size: 0.95rem;
|
||
font-weight: 500;
|
||
min-width: 70px;
|
||
text-align: center;
|
||
box-shadow: 0 2px 8px rgba(102, 126, 234, 0.15);
|
||
}
|
||
.lottery-type.active {
|
||
border: 2px solid #764ba2;
|
||
}
|
||
|
||
.order-content {
|
||
margin-bottom: 25px;
|
||
}
|
||
|
||
.order-info {
|
||
margin-bottom: 15px;
|
||
}
|
||
|
||
.order-info p {
|
||
margin: 5px 0;
|
||
color: #7f8c8d;
|
||
font-size: 0.95rem;
|
||
}
|
||
|
||
.order-numbers {
|
||
text-align: center;
|
||
padding: 20px 0 0 0;
|
||
border-radius: 8px;
|
||
}
|
||
|
||
.number-display {
|
||
display: flex;
|
||
align-items: center;
|
||
gap: 10px;
|
||
margin-bottom: 10px;
|
||
justify-content: center;
|
||
background: #f8f9fa;
|
||
border-radius: 8px;
|
||
padding: 12px 0;
|
||
box-shadow: 0 2px 8px rgba(102, 126, 234, 0.08);
|
||
}
|
||
.number-display.multi {
|
||
margin-bottom: 16px;
|
||
}
|
||
.order-index {
|
||
background: #e0e7ff;
|
||
color: #5f6ad2;
|
||
border-radius: 50%;
|
||
width: 28px;
|
||
height: 28px;
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: center;
|
||
font-weight: bold;
|
||
font-size: 1rem;
|
||
margin-right: 8px;
|
||
}
|
||
.ball {
|
||
display: inline-block;
|
||
width: 36px;
|
||
height: 36px;
|
||
border-radius: 50%;
|
||
text-align: center;
|
||
line-height: 36px;
|
||
font-weight: bold;
|
||
font-size: 1.1rem;
|
||
color: white;
|
||
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.2);
|
||
}
|
||
.ball.red {
|
||
background: linear-gradient(135deg, #e74c3c, #c0392b);
|
||
}
|
||
.ball.blue {
|
||
background: linear-gradient(135deg, #3498db, #2980b9);
|
||
}
|
||
.separator {
|
||
font-size: 1.5rem;
|
||
color: #7f8c8d;
|
||
font-weight: bold;
|
||
margin: 0 15px;
|
||
}
|
||
.recommend-type {
|
||
color: #27ae60;
|
||
font-weight: 500;
|
||
margin-left: 12px;
|
||
font-size: 0.98rem;
|
||
}
|
||
.no-order {
|
||
text-align: center;
|
||
padding: 40px 20px;
|
||
color: #7f8c8d;
|
||
}
|
||
.order-actions {
|
||
text-align: center;
|
||
}
|
||
.generate-btn {
|
||
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
|
||
color: white;
|
||
border: none;
|
||
padding: 15px 40px;
|
||
border-radius: 25px;
|
||
font-size: 1.1rem;
|
||
font-weight: 500;
|
||
cursor: pointer;
|
||
transition: all 0.3s ease;
|
||
box-shadow: 0 4px 15px rgba(102, 126, 234, 0.4);
|
||
}
|
||
.generate-btn:hover:not(:disabled) {
|
||
transform: translateY(-2px);
|
||
box-shadow: 0 6px 20px rgba(102, 126, 234, 0.6);
|
||
}
|
||
.generate-btn:disabled {
|
||
opacity: 0.7;
|
||
cursor: not-allowed;
|
||
}
|
||
.copy-all-btn {
|
||
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
|
||
color: white;
|
||
border: none;
|
||
padding: 15px 40px;
|
||
border-radius: 25px;
|
||
font-size: 1.1rem;
|
||
font-weight: 500;
|
||
cursor: pointer;
|
||
transition: all 0.3s ease;
|
||
box-shadow: 0 4px 15px rgba(102, 126, 234, 0.4);
|
||
margin-left: 16px;
|
||
}
|
||
.copy-all-btn:hover:not(:disabled) {
|
||
transform: translateY(-2px);
|
||
box-shadow: 0 6px 20px rgba(102, 126, 234, 0.6);
|
||
}
|
||
.copy-all-btn:disabled {
|
||
opacity: 0.7;
|
||
cursor: not-allowed;
|
||
}
|
||
|
||
.history-section {
|
||
background: white;
|
||
border-radius: 16px;
|
||
box-shadow: 0 6px 24px rgba(0, 0, 0, 0.10);
|
||
overflow: hidden;
|
||
margin-top: 40px;
|
||
}
|
||
.history-header {
|
||
display: flex;
|
||
justify-content: space-between;
|
||
align-items: center;
|
||
padding: 25px 30px;
|
||
border-bottom: 2px solid #f8f9fa;
|
||
}
|
||
.history-header h3 {
|
||
color: #2c3e50;
|
||
margin: 0;
|
||
font-size: 1.5rem;
|
||
}
|
||
.history-tabs {
|
||
display: flex;
|
||
gap: 10px;
|
||
}
|
||
.tab-btn {
|
||
background: #f8f9fa;
|
||
border: none;
|
||
padding: 10px 20px;
|
||
border-radius: 20px;
|
||
cursor: pointer;
|
||
font-weight: 500;
|
||
color: #764ba2;
|
||
}
|
||
.tab-btn.active {
|
||
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
|
||
color: white;
|
||
}
|
||
.history-content {
|
||
padding: 30px;
|
||
}
|
||
.history-group {
|
||
background: #f6f7fa;
|
||
border-radius: 18px;
|
||
box-shadow: 0 4px 18px rgba(102,126,234,0.08);
|
||
margin-bottom: 36px;
|
||
padding: 18px 24px 16px 24px;
|
||
}
|
||
.group-header {
|
||
display: flex;
|
||
align-items: center;
|
||
gap: 32px;
|
||
margin-bottom: 12px;
|
||
font-weight: bold;
|
||
color: #2c3e50;
|
||
font-size: 1.08rem;
|
||
}
|
||
.group-numbers {
|
||
display: flex;
|
||
flex-direction: column;
|
||
align-items: flex-start;
|
||
width: 100%;
|
||
}
|
||
.group-number-item {
|
||
display: flex;
|
||
align-items: center;
|
||
gap: 12px;
|
||
background: #fff;
|
||
border-radius: 10px;
|
||
box-shadow: 0 2px 8px rgba(102,126,234,0.08);
|
||
padding: 10px 16px;
|
||
min-width: 220px;
|
||
margin-bottom: 8px;
|
||
justify-content: flex-start;
|
||
}
|
||
.order-index {
|
||
background: #e0e7ff;
|
||
color: #5f6ad2;
|
||
border-radius: 50%;
|
||
width: 24px;
|
||
height: 24px;
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: center;
|
||
font-weight: bold;
|
||
font-size: 1rem;
|
||
margin-right: 8px;
|
||
}
|
||
.number-text {
|
||
font-size: 1.15rem;
|
||
font-family: 'Consolas', 'Menlo', 'Monaco', monospace;
|
||
color: #2c3e50;
|
||
letter-spacing: 2px;
|
||
font-weight: 600;
|
||
}
|
||
.copy-btn {
|
||
margin-left: 10px;
|
||
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
|
||
color: white;
|
||
border: none;
|
||
padding: 4px 16px;
|
||
border-radius: 16px;
|
||
font-size: 0.98rem;
|
||
font-weight: 500;
|
||
cursor: pointer;
|
||
transition: all 0.2s;
|
||
}
|
||
.copy-btn:hover {
|
||
background: linear-gradient(135deg, #764ba2 0%, #667eea 100%);
|
||
}
|
||
.recommend-type {
|
||
color: #27ae60;
|
||
font-weight: 500;
|
||
font-size: 0.95rem;
|
||
margin-left: 8px;
|
||
}
|
||
.check-win-btn {
|
||
margin-left: 24px;
|
||
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
|
||
color: white;
|
||
border: none;
|
||
padding: 8px 22px;
|
||
border-radius: 20px;
|
||
font-size: 1rem;
|
||
font-weight: 500;
|
||
cursor: pointer;
|
||
transition: all 0.3s;
|
||
box-shadow: 0 2px 8px rgba(102, 126, 234, 0.13);
|
||
}
|
||
.check-win-btn:disabled {
|
||
opacity: 0.6;
|
||
cursor: not-allowed;
|
||
}
|
||
.group-number-item.win {
|
||
border: 2px solid #27ae60;
|
||
box-shadow: 0 0 12px #27ae6040;
|
||
background: #eafaf1;
|
||
}
|
||
.win-info {
|
||
margin-left: 12px;
|
||
color: #27ae60;
|
||
font-weight: bold;
|
||
font-size: 1.05rem;
|
||
}
|
||
.win-level {
|
||
margin-right: 8px;
|
||
}
|
||
.win-amount {
|
||
background: #27ae60;
|
||
color: #fff;
|
||
border-radius: 8px;
|
||
padding: 2px 8px;
|
||
margin-left: 4px;
|
||
font-size: 0.98rem;
|
||
}
|
||
.not-win {
|
||
margin-left: 12px;
|
||
color: #aaa;
|
||
font-size: 0.98rem;
|
||
}
|
||
@media (max-width: 768px) {
|
||
.number-generator {
|
||
padding: 10px;
|
||
}
|
||
.header h1 {
|
||
font-size: 2rem;
|
||
}
|
||
.order-card {
|
||
padding: 16px;
|
||
}
|
||
.card-header {
|
||
flex-direction: column;
|
||
gap: 10px;
|
||
text-align: center;
|
||
}
|
||
.history-header {
|
||
flex-direction: column;
|
||
gap: 15px;
|
||
text-align: center;
|
||
}
|
||
.history-tabs {
|
||
width: 100%;
|
||
justify-content: center;
|
||
}
|
||
.history-content {
|
||
padding: 10px;
|
||
}
|
||
.history-group {
|
||
padding: 10px 4px 8px 4px;
|
||
}
|
||
.group-header {
|
||
flex-direction: column;
|
||
gap: 8px;
|
||
font-size: 0.98rem;
|
||
}
|
||
.group-numbers {
|
||
gap: 10px;
|
||
}
|
||
.group-number-item {
|
||
min-width: 140px;
|
||
padding: 6px 6px;
|
||
font-size: 0.9rem;
|
||
}
|
||
}
|
||
</style> |