fix(buyer): 优化秒杀页面布局与顶部搜索栏样式统一

- 增加秒杀顶部氛围横幅与数字倒计时模块
- 修复时间轴 Tab 场次少时异常拉伸撑满的问题,支持单场次居中对齐
- 重构秒杀商品网格与卡片排版,统一两行截断、进度条占位与按钮状态
- 顶部搜索栏统一引用 SearchHeader,规范整站搜索组件蓝色基调
This commit is contained in:
pikachu1995@126.com
2026-11-10 10:55:57 +08:00
parent 3c4604a342
commit f33c969d1e
2 changed files with 545 additions and 253 deletions

View File

@@ -449,12 +449,12 @@ onUnmounted(() => {
user-select: none; user-select: none;
&:hover { &:hover {
color: $theme_color; color: #409EFF;
} }
&.active { &.active {
color: #fff; color: #fff;
background: $theme_color; background: #409EFF;
} }
} }

View File

@@ -1,70 +1,134 @@
<template> <template>
<div class="seckill-list"> <div class="seckill-list">
<BaseHeader></BaseHeader> <BaseHeader></BaseHeader>
<Search /> <SearchHeader></SearchHeader>
<!-- 秒杀时间段 -->
<div class="promotion-decorate">限时秒杀</div> <!-- 秒杀顶部氛围横幅 -->
<ul class="time-line"> <div class="seckill-hero">
<template v-for="(time, index) in list"> <div class="hero-inner">
<li v-if="index < 5" @click="currIndex = index" :key="index" :class="{ currTimeline: currIndex === index }"> <div class="hero-left">
<div>{{ time.timeLine + ":00" }}</div> <div class="hero-tag">
<div v-if="currIndex === index"> <span class="lightning">⚡</span>
<p>{{ nowHour >= time.timeLine ? "秒杀中" : "即将开始" }}</p> <span>限时特惠 · 爆款直降</span>
<p>
{{ nowHour >= time.timeLine ? "距结束" : "距开始" }}&nbsp;{{
currTime
}}
</p>
</div> </div>
<div v-else class="not-curr"> <h1 class="hero-title">限时秒杀</h1>
{{ nowHour >= time.timeLine ? "秒杀中" : "即将开始" }} <p class="hero-subtitle">正品严选 · 限量低价 · 抢完即止</p>
</div>
<div class="hero-countdown" v-if="list.length && list[currIndex]">
<div class="countdown-badge">
<span class="status-dot" :class="{ 'is-live': isCurrentSessionActive }"></span>
<span>{{ isCurrentSessionActive ? "正在抢购中" : "即将准点开抢" }}</span>
</div>
<div class="countdown-label">
{{ isCurrentSessionActive ? "距本场结束仅剩" : "距本场开始仅剩" }}
</div>
<div class="countdown-boxes">
<span class="time-block">{{ countdownHours }}</span>
<span class="time-sep">:</span>
<span class="time-block">{{ countdownMinutes }}</span>
<span class="time-sep">:</span>
<span class="time-block">{{ countdownSeconds }}</span>
</div> </div>
</li>
</template>
</ul>
<!-- 秒杀商品列表 -->
<div class="seckill-goods-wrap">
<div class="goods-list">
<empty v-if="goodsList.length === 0" />
<div v-else class="goods-show-info1" v-for="(item, index) in goodsList" :key="index"
@click="goGoodsDetail(item.skuId, item.goodsId)">
<div class="goods-show-img">
<img :src="item.goodsImage" loading="lazy" decoding="async" :alt="item.goodsName" />
</div> </div>
<div class="goods-show-price">
<span class="seckill-price text-danger">{{ $filters.unitPrice(item.price, "¥") }}</span>
<span class="origin-price">{{ $filters.unitPrice(item.originalPrice, "¥") }}</span>
</div>
<div class="goods-show-detail">
<span>{{ item.goodsName }}</span>
</div>
<div v-if="nowHour >= list[currIndex].timeLine" class="goods-show-num1">
<span>已售{{ salePercent(item) }}%</span>
<el-progress
:show-text="false"
:color="'var(--theme-color, #ff3c2a)'"
:percentage="salePercent(item)"
/>
</div>
<div class="goods-show-seller">
<span>{{ item.storeName }}</span>
</div>
<div
class="goods-seckill-btn"
:class="{ 'is-disabled': !canBuy(item) }"
>
{{ buyText(item) }}
</div>
</div>
</div> </div>
</div> </div>
<!-- 秒杀时间段导航 -->
<div class="time-line-wrap" v-if="list.length">
<ul class="time-line" :class="{ 'single-session': list.length === 1 }">
<template v-for="(time, index) in list">
<li
v-if="index < 5"
:key="index"
@click="currIndex = index"
:class="{ currTimeline: currIndex === index }"
>
<div class="timeline-hour">{{ time.timeLine + ":00" }}</div>
<div class="timeline-status">
<span class="status-pill">{{ nowHour >= time.timeLine ? "秒杀中" : "即将开始" }}</span>
</div>
</li>
</template>
</ul>
</div>
<!-- 秒杀商品列表 -->
<div class="seckill-goods-wrap">
<div v-if="goodsList.length === 0" class="empty-wrap">
<empty :_Title="list.length ? '当前场次暂无秒杀商品,去其他场次看看吧' : '今日暂无秒杀活动,去首页逛逛吧'" />
</div>
<div v-else class="goods-grid">
<div
class="goods-card"
v-for="(item, index) in goodsList"
:key="index"
@click="goGoodsDetail(item.skuId, item.goodsId)"
>
<div class="goods-img-box">
<img :src="item.goodsImage" loading="lazy" decoding="async" :alt="item.goodsName" />
<div v-if="isSoldOut(item)" class="sold-out-overlay">
<span>已抢光</span>
</div>
</div>
<div class="goods-price-row">
<div class="price-main">
<span class="price-symbol">¥</span>
<span class="price-val">{{ $filters.unitPrice(item.price, "") }}</span>
</div>
<div class="price-origin">
{{ $filters.unitPrice(item.originalPrice, "¥") }}
</div>
</div>
<div class="goods-name-row" :title="item.goodsName">
{{ item.goodsName }}
</div>
<div class="goods-progress-row">
<template v-if="nowHour >= list[currIndex].timeLine">
<span class="progress-label">已抢 {{ salePercent(item) }}%</span>
<el-progress
:show-text="false"
:stroke-width="6"
:color="'var(--theme-color, #ff3c2a)'"
:percentage="salePercent(item)"
/>
</template>
<template v-else>
<span class="upcoming-tip">限量抢购 · 准点开抢</span>
</template>
</div>
<div class="goods-store-row" :title="item.storeName">
<span class="store-name">{{ item.storeName }}</span>
</div>
<div
class="goods-action-btn"
:class="{
'btn-disabled': !canBuy(item),
'btn-upcoming': nowHour < list[currIndex].timeLine,
'btn-active': canBuy(item)
}"
>
{{ buyText(item) }}
</div>
</div>
</div>
</div>
<BaseFooter /> <BaseFooter />
</div> </div>
</template> </template>
<script setup> <script setup>
import { onBeforeUnmount, onMounted, ref, watch } from "vue"; import { computed, onBeforeUnmount, onMounted, ref, watch } from "vue";
import { useRouter } from "vue-router"; import { useRouter } from "vue-router";
import { seckillByDay } from "@/api/promotion"; import { seckillByDay } from "@/api/promotion";
import SearchHeader from "@/components/indexDecorate/components/SearchHeader.vue";
const router = useRouter(); const router = useRouter();
@@ -72,10 +136,19 @@ const list = ref([]); // 秒杀时段列表
const goodsList = ref([]); // 商品列表 const goodsList = ref([]); // 商品列表
let interval = null; // 定时器 let interval = null; // 定时器
const currIndex = ref(0); // 当前时间段的下标 const currIndex = ref(0); // 当前时间段的下标
const currTime = ref(0); // 当前显示的倒计时 const currTime = ref("00:00:00"); // 当前显示的倒计时格式字符串
const diffSeconds = ref(0); // 倒计时时间戳 const countdownHours = ref("00");
const countdownMinutes = ref("00");
const countdownSeconds = ref("00");
const diffSeconds = ref(0); // 倒计时时间戳差值
const nowHour = ref(new Date().getHours()); // 当前小时数 const nowHour = ref(new Date().getHours()); // 当前小时数
// 当前选中场次是否处于开抢中
const isCurrentSessionActive = computed(() => {
if (!list.value.length || !list.value[currIndex.value]) return false;
return nowHour.value >= list.value[currIndex.value].timeLine;
});
watch(currIndex, (val) => { watch(currIndex, (val) => {
clearInterval(interval); clearInterval(interval);
interval = null; interval = null;
@@ -85,26 +158,22 @@ watch(currIndex, (val) => {
}); });
watch(diffSeconds, (val) => { watch(diffSeconds, (val) => {
const hours = Math.floor(val / 3600);
// 当前秒数 / 60,向下取整
// 获取到所有分钟数 3600 / 60 = 60分钟
// 对60取模,超过小时数的分钟数
const minutes = Math.floor(val / 60) % 60;
// 当前的秒数 % 60,获取到 超过小时数、分钟数的秒数(秒数)
const seconds = val % 60;
currTime.value =
filteTime(hours) + ":" + filteTime(minutes) + ":" + filteTime(seconds);
if (val <= 0) { if (val <= 0) {
clearInterval(interval); clearInterval(interval);
interval = null; interval = null;
countdownHours.value = "00";
countdownMinutes.value = "00";
countdownSeconds.value = "00";
currTime.value = "00:00:00";
return;
} }
function filteTime (time) { const hours = Math.floor(val / 3600);
if (time < 10) { const minutes = Math.floor(val / 60) % 60;
return "0" + time; const seconds = val % 60;
} else { countdownHours.value = hours < 10 ? "0" + hours : String(hours);
return time; countdownMinutes.value = minutes < 10 ? "0" + minutes : String(minutes);
} countdownSeconds.value = seconds < 10 ? "0" + seconds : String(seconds);
} currTime.value = `${countdownHours.value}:${countdownMinutes.value}:${countdownSeconds.value}`;
}); });
function getListByDay () { function getListByDay () {
@@ -120,7 +189,7 @@ function getListByDay () {
function goGoodsDetail (skuId, goodsId) { function goGoodsDetail (skuId, goodsId) {
// 跳转商品详情 // 跳转商品详情
let routeUrl = router.resolve({ const routeUrl = router.resolve({
path: "/goodsDetail", path: "/goodsDetail",
query: { skuId, goodsId }, query: { skuId, goodsId },
}); });
@@ -135,41 +204,46 @@ function salePercent (item) {
// 场次已开始,且销量达到库存 // 场次已开始,且销量达到库存
function isSoldOut (item) { function isSoldOut (item) {
if (!list.value[currIndex.value]) return false;
return nowHour.value >= list.value[currIndex.value].timeLine && item.quantity <= item.salesNum; return nowHour.value >= list.value[currIndex.value].timeLine && item.quantity <= item.salesNum;
} }
// 场次已开始且未售罄才可抢 // 场次已开始且未售罄才可抢
function canBuy (item) { function canBuy (item) {
if (!list.value[currIndex.value]) return false;
return nowHour.value >= list.value[currIndex.value].timeLine && !isSoldOut(item); return nowHour.value >= list.value[currIndex.value].timeLine && !isSoldOut(item);
} }
// 按钮文案:未开始 / 已售罄 / 立即抢购 // 按钮文案:未开始 / 已售罄 / 立即抢购
function buyText (item) { function buyText (item) {
if (!list.value[currIndex.value]) return "即将开始";
if (nowHour.value < list.value[currIndex.value].timeLine) return "即将开始"; if (nowHour.value < list.value[currIndex.value].timeLine) return "即将开始";
if (isSoldOut(item)) return "已售罄"; if (isSoldOut(item)) return "已售罄";
return "立即抢购"; return "立即抢购";
} }
function countDown (currIndex) { function countDown (currIndex) {
// 倒计时 if (!list.value[currIndex]) return;
// 0点时间戳 // 倒计时:0点时间戳
let zeroTime = new Date(new Date().toLocaleDateString()).getTime(); const zeroTime = new Date(new Date().toLocaleDateString()).getTime();
let currTime = new Date().getTime(); const currTimeMs = new Date().getTime();
let actTime = 0; let actTime = 0;
let nowHour = new Date().getHours(); // 当前小时数 const currentHour = new Date().getHours();
if (list.value[currIndex].timeLine > nowHour) { nowHour.value = currentHour;
// 活动未开始
if (list.value[currIndex].timeLine > currentHour) {
// 活动未开始:距开始时间
actTime = zeroTime + list.value[currIndex].timeLine * 3600 * 1000; actTime = zeroTime + list.value[currIndex].timeLine * 3600 * 1000;
} else if (list.value[currIndex].timeLine <= nowHour) { } else {
// 活动进行中 // 活动进行中:距结束时间
if (currIndex === list.value.length - 1) { if (currIndex === list.value.length - 1) {
// 如果是最后一个活动,直到24点结束
actTime = zeroTime + 24 * 3600 * 1000; actTime = zeroTime + 24 * 3600 * 1000;
} else { } else {
actTime = zeroTime + list.value[currIndex + 1].timeLine * 3600 * 1000; actTime = zeroTime + list.value[currIndex + 1].timeLine * 3600 * 1000;
} }
} }
diffSeconds.value = Math.floor((actTime - currTime) / 1000);
diffSeconds.value = Math.max(0, Math.floor((actTime - currTimeMs) / 1000));
interval = setInterval(() => { interval = setInterval(() => {
diffSeconds.value--; diffSeconds.value--;
}, 1000); }, 1000);
@@ -183,216 +257,434 @@ onBeforeUnmount(() => {
clearInterval(interval); clearInterval(interval);
}); });
</script> </script>
<style lang="scss" scoped> <style lang="scss" scoped>
@import "../../assets/styles/goodsList.scss";
.seckill-list { .seckill-list {
background: #f5f5f5; background: #f7f8fa;
min-height: 100vh;
} }
.promotion-decorate { /* 顶部氛围 Hero 横幅 */
width: auto; .seckill-hero {
margin: 28px auto 16px; background: linear-gradient(135deg, #e52d27 0%, #b31217 60%, #790c10 100%);
color: #171A26; color: #fff;
font-size: 22px; padding: 30px 0 38px;
font-weight: 600; box-shadow: inset 0 -4px 12px rgba(0, 0, 0, 0.15);
&::before, .hero-inner {
&::after { width: 1200px;
display: none; margin: 0 auto;
display: flex;
align-items: center;
justify-content: space-between;
} }
}
.time-line { .hero-left {
width: 1200px; display: flex;
max-width: 1200px; flex-direction: column;
height: auto; gap: 8px;
margin: 0 auto;
background: #fff;
display: flex;
box-sizing: border-box;
border-radius: 8px;
overflow: hidden;
li { .hero-tag {
flex: 1; display: inline-flex;
width: auto; align-items: center;
min-height: 78px; gap: 6px;
padding: 12px 20px; padding: 3px 10px;
background: rgba(255, 255, 255, 0.2);
border-radius: 20px;
font-size: 13px;
width: fit-content;
backdrop-filter: blur(4px);
.lightning {
color: #ffeb3b;
font-weight: bold;
}
}
.hero-title {
margin: 0;
font-size: 34px;
font-weight: 800;
letter-spacing: 2px;
text-shadow: 0 2px 4px rgba(0, 0, 0, 0.25);
}
.hero-subtitle {
margin: 0;
font-size: 14px;
color: rgba(255, 255, 255, 0.85);
letter-spacing: 1px;
}
}
.hero-countdown {
background: rgba(0, 0, 0, 0.25);
border: 1px solid rgba(255, 255, 255, 0.2);
border-radius: 12px;
padding: 16px 24px;
backdrop-filter: blur(8px);
display: flex; display: flex;
flex-direction: column; flex-direction: column;
align-items: center; align-items: center;
justify-content: center; gap: 8px;
text-align: center; box-shadow: 0 8px 20px rgba(0, 0, 0, 0.18);
gap: 4px;
font-size: 18px;
font-weight: 600;
color: #171A26;
box-sizing: border-box;
& + li { .countdown-badge {
box-shadow: inset 1px 0 0 #f2f2f2; display: flex;
} align-items: center;
gap: 6px;
&:hover {
cursor: pointer;
background: #fafafa;
}
p {
margin: 0;
font-size: 13px; font-size: 13px;
font-weight: 400;
line-height: 18px;
}
.not-curr {
border: none;
border-radius: 0;
padding: 0;
margin: 0;
font-size: 13px;
font-weight: 400;
color: #999;
}
}
.currTimeline {
background: $theme_color;
color: #fff;
&:hover {
background: $theme_color;
}
> div:nth-child(1) {
font-size: 22px;
line-height: 28px;
}
> div:nth-child(2) {
margin-left: 0;
}
.not-curr {
color: #fff; color: #fff;
font-weight: 500;
.status-dot {
width: 8px;
height: 8px;
border-radius: 50%;
background: #ffc107;
&.is-live {
background: #4caf50;
box-shadow: 0 0 8px #4caf50;
}
}
}
.countdown-label {
font-size: 13px;
color: rgba(255, 255, 255, 0.9);
}
.countdown-boxes {
display: flex;
align-items: center;
gap: 6px;
.time-block {
display: inline-block;
min-width: 38px;
height: 38px;
line-height: 38px;
text-align: center;
background: #1e1e1e;
color: #ffeb3b;
font-size: 20px;
font-weight: 700;
font-family: Consolas, Monaco, monospace;
border-radius: 6px;
padding: 0 4px;
box-shadow: 0 3px 6px rgba(0, 0, 0, 0.3);
}
.time-sep {
font-size: 20px;
font-weight: bold;
color: #fff;
}
} }
} }
} }
/* 时间轴导航 */
.time-line-wrap {
width: 1200px;
margin: -18px auto 0;
position: relative;
z-index: 10;
.time-line {
list-style: none;
padding: 0;
margin: 0;
background: #fff;
border-radius: 10px;
box-shadow: 0 6px 18px rgba(0, 0, 0, 0.06);
display: flex;
overflow: hidden;
&.single-session {
justify-content: center;
li {
max-width: 300px;
}
}
li {
flex: 1;
min-width: 160px;
max-width: 240px;
height: 68px;
padding: 10px 16px;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
gap: 4px;
cursor: pointer;
background: #fff;
color: #333;
transition: all 0.2s ease;
position: relative;
box-sizing: border-box;
& + li {
box-shadow: inset 1px 0 0 #f0f0f0;
}
&:hover:not(.currTimeline) {
background: #fafafa;
color: var(--theme-color, #e52d27);
}
.timeline-hour {
font-size: 19px;
font-weight: 700;
line-height: 22px;
}
.timeline-status {
.status-pill {
display: inline-block;
font-size: 12px;
padding: 1px 8px;
border-radius: 10px;
background: #f5f5f5;
color: #888;
line-height: 16px;
}
}
}
.currTimeline {
background: linear-gradient(135deg, var(--theme-color, #e52d27) 0%, #ff5252 100%);
color: #fff;
box-shadow: 0 4px 12px rgba(229, 45, 39, 0.3);
&:hover {
background: linear-gradient(135deg, var(--theme-color, #e52d27) 0%, #ff5252 100%);
}
.timeline-hour {
font-size: 21px;
}
.timeline-status {
.status-pill {
background: rgba(255, 255, 255, 0.25);
color: #fff;
font-weight: 500;
}
}
}
}
}
/* 秒杀商品容器 */
.seckill-goods-wrap { .seckill-goods-wrap {
width: 1200px; width: 1200px;
max-width: 1200px; margin: 20px auto 50px;
margin: 16px auto 40px;
padding: 16px;
box-sizing: border-box;
background: #fff; background: #fff;
border-radius: 8px; border-radius: 10px;
min-height: 320px; padding: 24px;
box-sizing: border-box;
min-height: 380px;
box-shadow: 0 4px 16px rgba(0, 0, 0, 0.04);
.goods-list { .empty-wrap {
width: 100%; padding: 60px 0;
margin: 0;
column-gap: 16px;
} }
:deep(.empty) { .goods-grid {
margin: 48px 0; display: grid;
color: #999; grid-template-columns: repeat(4, 1fr);
gap: 20px;
} }
} }
.goods-show-info1 { /* 商品卡片 */
width: calc(25% - 12px); .goods-card {
min-width: 0; background: #fff;
padding: 12px; border: 1px solid #ebebeb;
margin: 0 0 16px;
position: relative;
border: 1px solid #f0f0f0;
border-radius: 8px; border-radius: 8px;
cursor: pointer; padding: 12px;
background-color: #fff;
box-sizing: border-box; box-sizing: border-box;
display: flex; display: flex;
flex-direction: column; flex-direction: column;
cursor: pointer;
transition: all 0.25s cubic-bezier(0.25, 0.8, 0.25, 1);
position: relative;
&:hover { &:hover {
border-color: #eee; border-color: #ffd0d0;
box-shadow: 0 6px 16px rgba(0, 0, 0, 0.06); transform: translateY(-4px);
box-shadow: 0 10px 24px rgba(229, 45, 39, 0.12);
} }
}
.goods-show-img { .goods-img-box {
display: flex; position: relative;
justify-content: center;
border-radius: 6px;
overflow: hidden;
background: #fafafa;
img {
width: 100%; width: 100%;
height: auto;
aspect-ratio: 1; aspect-ratio: 1;
object-fit: cover; border-radius: 6px;
} overflow: hidden;
} background: #f9f9f9;
.goods-show-price { img {
display: flex; width: 100%;
align-items: baseline; height: 100%;
gap: 8px; object-fit: cover;
margin-top: 10px; transition: transform 0.3s ease;
} }
.origin-price { &:hover img {
color: #999; transform: scale(1.03);
font-size: 13px; }
text-decoration: line-through;
}
.goods-show-detail { .sold-out-overlay {
height: 40px; position: absolute;
margin: 8px 0; inset: 0;
color: #333; background: rgba(0, 0, 0, 0.55);
font-size: 14px; display: flex;
line-height: 20px; align-items: center;
} justify-content: center;
.goods-show-num1 { span {
display: flex; display: inline-block;
align-items: center; padding: 6px 14px;
gap: 8px; border-radius: 20px;
font-size: 12px; background: rgba(255, 255, 255, 0.9);
margin-bottom: 8px; color: #333;
color: #666; font-size: 13px;
font-weight: 600;
span { }
flex-shrink: 0; }
} }
:deep(.el-progress) { .goods-price-row {
flex: 1; display: flex;
align-items: baseline;
gap: 8px;
margin-top: 12px;
.price-main {
color: var(--theme-color, #e52d27);
font-weight: 800;
display: flex;
align-items: baseline;
.price-symbol {
font-size: 14px;
}
.price-val {
font-size: 22px;
font-family: Arial, Helvetica, sans-serif;
}
}
.price-origin {
font-size: 13px;
color: #aaa;
text-decoration: line-through;
}
} }
}
.goods-show-seller { .goods-name-row {
margin-bottom: 10px; margin-top: 8px;
color: #999; height: 40px;
font-size: 13px; font-size: 14px;
} line-height: 20px;
color: #333;
overflow: hidden;
text-overflow: ellipsis;
display: -webkit-box;
-webkit-line-clamp: 2;
-webkit-box-orient: vertical;
word-break: break-all;
font-weight: 500;
}
.goods-seckill-btn { .goods-progress-row {
margin-top: auto; margin-top: 10px;
height: 34px; height: 20px;
border-radius: 4px; display: flex;
color: #fff; align-items: center;
text-align: center; gap: 8px;
line-height: 34px; font-size: 12px;
font-size: 14px; color: #777;
background-color: $theme_color;
&.is-disabled { .progress-label {
background: #c8c8c8; flex-shrink: 0;
}
:deep(.el-progress) {
flex: 1;
margin: 0;
}
.upcoming-tip {
color: #e67e22;
font-size: 12px;
background: #fff8f0;
padding: 2px 8px;
border-radius: 4px;
}
}
.goods-store-row {
margin-top: 8px;
margin-bottom: 12px;
font-size: 12px;
color: #999;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
.store-name {
&:hover {
color: var(--theme-color, #e52d27);
}
}
}
.goods-action-btn {
margin-top: auto;
height: 36px;
border-radius: 6px;
display: flex;
align-items: center;
justify-content: center;
font-size: 14px;
font-weight: 600;
transition: all 0.2s ease;
user-select: none;
&.btn-active {
background: linear-gradient(135deg, var(--theme-color, #e52d27) 0%, #ff5252 100%);
color: #fff;
box-shadow: 0 4px 10px rgba(229, 45, 39, 0.25);
&:hover {
opacity: 0.92;
box-shadow: 0 6px 14px rgba(229, 45, 39, 0.35);
}
}
&.btn-upcoming {
background: #ff9800;
color: #fff;
&:hover {
opacity: 0.92;
}
}
&.btn-disabled {
background: #e0e0e0;
color: #888;
cursor: not-allowed;
box-shadow: none;
}
} }
} }
</style> </style>