🐛 fix: 恢复卡片上浮与步骤脉冲,并锁定 Cookie 登录禁用

- 卡片 hover 恢复 translateY(-5px),禁用态不响应
- 步骤脉冲恢复 scale+外扩环,使用高对比色避免黄底不可见
- updateLoginCardsState 不再随服务时间启用 Cookie 入口
This commit is contained in:
Abner
2026-07-11 13:14:58 +08:00
parent 41ec3a91b7
commit de9db76f56
8 changed files with 140 additions and 44 deletions

View File

@@ -287,7 +287,17 @@ class GiffgaffApp {
const bindCard = (el, method) => {
if (!el || el.__bound) return;
el.__bound = true;
const handler = () => uiController.selectLoginMethod(method);
const handler = () => {
// 禁用态(含 Cookie 暂不可用)不响应
if (
el.classList.contains('disabled') ||
el.getAttribute('aria-disabled') === 'true' ||
el.style.pointerEvents === 'none'
) {
return;
}
uiController.selectLoginMethod(method);
};
el.addEventListener('click', handler);
el.addEventListener('keydown', (e) => {
if (e.key === 'Enter' || e.key === ' ') {
@@ -298,6 +308,7 @@ class GiffgaffApp {
};
bindCard(oauthCard, 'oauth');
// Cookie 入口保留绑定以便未来恢复,但 updateLoginCardsState 会始终禁用
bindCard(cookieCard, 'cookie');
}
@@ -1466,30 +1477,40 @@ class GiffgaffApp {
const oauthCard = document.getElementById('oauthCard');
const cookieCard = document.getElementById('cookieCard');
// 更新卡片状态
[oauthCard, cookieCard].forEach(card => {
if (!card) return;
// 仅 OAuth 受服务时间影响
if (oauthCard) {
if (isAvailable) {
// 服务时间内:启用卡片
card.classList.remove('disabled', 'service-time-disabled');
card.style.cursor = 'pointer';
card.style.opacity = '1';
card.style.pointerEvents = 'auto';
card.removeAttribute('aria-disabled');
card.setAttribute('role', 'button');
card.setAttribute('tabindex', '0');
oauthCard.classList.remove('disabled', 'service-time-disabled');
oauthCard.style.cursor = 'pointer';
oauthCard.style.opacity = '1';
oauthCard.style.pointerEvents = 'auto';
oauthCard.removeAttribute('aria-disabled');
oauthCard.setAttribute('role', 'button');
oauthCard.setAttribute('tabindex', '0');
} else {
// 服务时间外:禁用卡片
card.classList.add('disabled', 'service-time-disabled');
card.style.cursor = 'not-allowed';
card.style.opacity = '0.5';
card.style.pointerEvents = 'none';
card.setAttribute('aria-disabled', 'true');
card.removeAttribute('role');
card.setAttribute('tabindex', '-1');
oauthCard.classList.add('disabled', 'service-time-disabled');
oauthCard.style.cursor = 'not-allowed';
oauthCard.style.opacity = '0.5';
oauthCard.style.pointerEvents = 'none';
oauthCard.setAttribute('aria-disabled', 'true');
oauthCard.removeAttribute('role');
oauthCard.setAttribute('tabindex', '-1');
}
});
}
// Cookie 登录当前暂不可用:始终禁用,切勿随服务时间重新启用
if (cookieCard) {
cookieCard.classList.add('disabled');
cookieCard.classList.remove('service-time-disabled');
cookieCard.style.cursor = 'not-allowed';
cookieCard.style.opacity = '0.5';
cookieCard.style.pointerEvents = 'none';
cookieCard.style.backgroundColor = '#f8f9fa';
cookieCard.setAttribute('aria-disabled', 'true');
cookieCard.setAttribute('aria-label', 'Cookie 登录暂不可用');
cookieCard.removeAttribute('role');
cookieCard.setAttribute('tabindex', '-1');
}
}
/**

View File

@@ -203,6 +203,20 @@ export class UIController {
this.elements.cookieLoginSection.style.display = 'none';
this.showStatus(this.elements.loginMethodStatus, tl('已选择OAuth 2.0登录方式'), "success");
} else if (method === 'cookie') {
// Cookie 登录当前暂不可用(与页面文案一致)
const cookieCard = document.getElementById('cookieCard');
if (
cookieCard &&
(cookieCard.classList.contains('disabled') ||
cookieCard.getAttribute('aria-disabled') === 'true')
) {
this.showStatus(
this.elements.loginMethodStatus,
tl('Cookie 登录暂不可用,请使用 OAuth 登录'),
'error'
);
return;
}
this.elements.oauthLoginSection.style.display = 'none';
this.elements.cookieLoginSection.style.display = 'block';
this.showStatus(this.elements.loginMethodStatus, tl('已选择Cookie登录方式'), "success");

View File

@@ -80,26 +80,51 @@ textarea:focus, input:focus {
background: rgba(255, 255, 255, 1);
}
/* 卡片样式:内容卡仅微调阴影,避免填表时大幅上浮 */
/* 卡片样式(恢复原上浮效果) */
.card {
background: rgba(255, 255, 255, 0.92);
background: rgba(255, 255, 255, 0.9);
border-radius: 16px;
border: 1px solid rgba(255, 204, 0, 0.3);
box-shadow: 0 4px 20px rgba(0, 0, 0, 0.08);
box-shadow: 0 4px 25px rgba(0, 0, 0, 0.1);
margin-bottom: 30px;
overflow: hidden;
transition:
transform var(--transition-base, 240ms ease),
box-shadow var(--transition-base, 240ms ease),
border-color var(--transition-base, 240ms ease);
}
@media (hover: hover) {
.card:hover {
box-shadow: 0 6px 24px rgba(0, 0, 0, 0.1);
border-color: rgba(255, 204, 0, 0.45);
transform: translateY(-5px);
box-shadow: 0 8px 30px rgba(0, 0, 0, 0.15);
border-color: rgba(255, 204, 0, 0.5);
}
}
/* 禁用卡片不可点、不上浮Cookie 等永久禁用) */
.card.disabled,
.card[aria-disabled="true"] {
cursor: not-allowed !important;
opacity: 0.5 !important;
pointer-events: none !important;
transform: none !important;
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.06) !important;
}
@media (hover: hover) {
.card.disabled:hover,
.card[aria-disabled="true"]:hover {
transform: none !important;
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.06) !important;
border-color: inherit;
}
}
#cookieCard {
background-color: #f8f9fa !important;
}
.card-header {
background: rgba(255, 204, 0, 0.1);
padding: 20px 25px;
@@ -181,11 +206,18 @@ textarea:focus, input:focus {
@media (hover: hover) {
.card:hover {
box-shadow: 0 6px 24px rgba(0, 0, 0, 0.45);
transform: translateY(-5px);
box-shadow: 0 8px 30px rgba(0, 0, 0, 0.45);
border-color: rgba(255, 204, 0, 0.38);
}
}
#cookieCard,
.card.disabled,
.card[aria-disabled="true"] {
background-color: #2a2a2a !important;
}
.card-header {
background: rgba(255, 204, 0, 0.1);
color: #f8f9fa;

View File

@@ -275,9 +275,10 @@
.step.active .step-number {
background: linear-gradient(135deg, #ffcc00, #ffd84d);
color: #212529;
box-shadow: 0 6px 16px rgba(255, 193, 7, 0.45);
border-color: rgba(255, 193, 7, 0.85);
transform: scale(1.06);
/* 静态阴影交给 pulse-ring 动画;颜色用高对比琥珀,避免黄底上看不见 */
--step-pulse-color: rgba(180, 83, 9, 0.75);
animation: pulse-ring var(--anim-base, 2.75s) var(--anim-ease-pulse, cubic-bezier(0.4, 0, 0.6, 1)) infinite;
}
.step.active .step-text {

View File

@@ -146,8 +146,9 @@ body {
background: linear-gradient(135deg, #ff7a1a, #ffb066);
color: #fff;
border-color: rgba(255, 107, 0, 0.85);
box-shadow: 0 6px 16px rgba(255, 107, 0, 0.45);
transform: scale(1.06);
/* 脉冲环用偏深橙,在橙色圆上仍清晰 */
--step-pulse-color: rgba(194, 65, 12, 0.75);
animation: pulse-ring var(--anim-base, 2.75s) var(--anim-ease-pulse, cubic-bezier(0.4, 0, 0.6, 1)) infinite;
}
.step.active .step-text {

View File

@@ -3,23 +3,41 @@
* 定义卡片、按钮、状态面板等组件样式
*/
/* 卡片样式:内容卡仅微调阴影,避免填表时大幅上浮 */
/* 卡片样式(恢复原上浮效果) */
.card {
background: rgba(255, 255, 255, 0.92);
background: rgba(255, 255, 255, 0.9);
border-radius: 16px;
border: 1px solid rgba(255, 107, 0, 0.3);
box-shadow: 0 4px 20px rgba(0, 0, 0, 0.08);
box-shadow: 0 4px 25px rgba(0, 0, 0, 0.1);
margin-bottom: 30px;
overflow: hidden;
transition:
transform var(--transition-base, 240ms ease),
box-shadow var(--transition-base, 240ms ease),
border-color var(--transition-base, 240ms ease);
}
@media (hover: hover) {
.card:hover {
box-shadow: 0 6px 24px rgba(0, 0, 0, 0.1);
border-color: rgba(255, 107, 0, 0.45);
transform: translateY(-5px);
box-shadow: 0 8px 30px rgba(0, 0, 0, 0.15);
border-color: rgba(255, 107, 0, 0.5);
}
}
.card.disabled,
.card[aria-disabled="true"] {
cursor: not-allowed !important;
opacity: 0.5 !important;
pointer-events: none !important;
transform: none !important;
}
@media (hover: hover) {
.card.disabled:hover,
.card[aria-disabled="true"]:hover {
transform: none !important;
box-shadow: 0 4px 25px rgba(0, 0, 0, 0.1) !important;
}
}
@@ -389,7 +407,8 @@
@media (hover: hover) {
.card:hover {
box-shadow: 0 6px 24px rgba(0, 0, 0, 0.45);
transform: translateY(-5px);
box-shadow: 0 8px 30px rgba(0, 0, 0, 0.45);
border-color: rgba(255, 107, 0, 0.42);
}
}

View File

@@ -227,15 +227,22 @@
100% { background-position: -200% 0; }
}
/* 步骤脉冲环(颜色跟随品牌 --primary */
/*
* 步骤当前态脉冲环恢复原效果scale + 外扩阴影)
* --step-pulse-color 默认用高对比蓝;品牌页可覆盖
* 注意:不可用与步骤圆同色的 --primary如 giffgaff 黄),否则几乎看不见
*/
@keyframes pulse-ring {
0% {
box-shadow: 0 0 0 0 color-mix(in srgb, var(--primary, #0d6efd) 55%, transparent);
transform: scale(0.95);
box-shadow: 0 0 0 0 var(--step-pulse-color, rgba(13, 110, 253, 0.7));
}
70% {
box-shadow: 0 0 0 10px color-mix(in srgb, var(--primary, #0d6efd) 0%, transparent);
transform: scale(1);
box-shadow: 0 0 0 10px color-mix(in srgb, var(--step-pulse-color, rgba(13, 110, 253, 0.7)) 0%, transparent);
}
100% {
box-shadow: 0 0 0 0 color-mix(in srgb, var(--primary, #0d6efd) 0%, transparent);
transform: scale(0.95);
box-shadow: 0 0 0 0 color-mix(in srgb, var(--step-pulse-color, rgba(13, 110, 253, 0.7)) 0%, transparent);
}
}

View File

@@ -564,9 +564,10 @@ html[data-page-hidden="true"] .step.active .step-number {
}
}
/* Step Indicator当前步脉冲颜色跟随 --primary */
/* Step Indicator当前步脉冲keyframes 见 animations.css */
.step.active .step-number {
animation: pulse-ring var(--anim-base, 2.75s) var(--anim-ease-pulse, var(--ease-out)) infinite;
--step-pulse-color: rgba(13, 110, 253, 0.7);
animation: pulse-ring var(--anim-base, 2.75s) var(--anim-ease-pulse, cubic-bezier(0.4, 0, 0.6, 1)) infinite;
}
/* 步骤指示器进度轨(--step-progress: 0~1由 JS 写入) */