feat(ui): 优化苹果卡支付页面及交互体验

- 新增苹果卡支付页面,采用更接近Apple风格的UI设计
- 引入TailwindCSS和GSAP动画库,实现流畅动画效果
- 设计渐变主色调,优化输入框和按钮样式
- 实现模态框(警告与详情)的显示与关闭动画
- 支持复制卡片标题功能,兼容多种复制方案并提供用户提示
- 添加跳转京东/淘宝购买按钮及其交互逻辑
- 实现智能粘贴识别,可从文本自动提取卡号和卡密
- 优化提交按钮交互,添加输入校验及请求状态反馈
- 支持移动端响应式布局和交互适配
- 隐藏滚动条,增强页面视觉美感和一致性
This commit is contained in:
danial
2025-11-19 21:12:51 +08:00
parent 146efec222
commit 6a00417ced
2 changed files with 924 additions and 0 deletions

Binary file not shown.

After

Width:  |  Height:  |  Size: 19 KiB

924
views/index-apple-v2.html Normal file
View File

@@ -0,0 +1,924 @@
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>苹果卡 - 安全支付</title>
<!-- 引入TailwindCSS -->
<script src="../static/js/tailwindcss.js"></script>
<!-- 引入GSAP动画库 -->
<script src="../static/js/gsap.min.js"></script>
<link rel="stylesheet" href="../static/css/index-anxin.css">
<style>
/* 引入更接近 Apple 风格的字体 */
@import url('https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;600;700&display=swap');
:root {
/* 定义渐变主色调 */
--primary-gradient: linear-gradient(135deg, #0077ed 0%, #0056b3 100%);
--primary-color-start: #0077ed;
/* 渐变起始色,用于 focus 等 */
--primary-color-end: #0056b3;
/* 渐变结束色 */
--secondary-color: #f5f5f7;
/* Apple Light Gray */
--text-color: #1d1d1f;
/* Apple Dark Gray */
--accent-color: #ff375f;
/* Apple Pink/Red Accent */
--border-color: #d2d2d7;
--bs-orange: #ff4d00;
--bs-blue: #0364cb;
--bs-green: #049325;
--bs-red: #bb091b;
--bs-yellow: #b48c13;
--bs-purple: #4c1ea2;
--bs-pink: #b91461;
--bs-gray: #515d67;
--bs-info: #0168cf;
/* Apple Border Gray */
--glow-color-start: rgba(0, 113, 227, 0.1);
/* 弥散光起始颜色 */
--glow-color-end: rgba(245, 245, 247, 0);
/* 弥散光结束颜色 (透明) */
}
body {
font-family: 'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, Cantarell, 'Open Sans', 'Helvetica Neue', sans-serif;
/* 添加弥散光背景 */
background: radial-gradient(circle at top center, var(--glow-color-start) 0%, var(--glow-color-end) 60%), var(--secondary-color);
color: var(--text-color);
min-height: 100vh;
overflow: auto;
/* 允许滚动 */
display: flex;
flex-direction: column;
}
/* 模态框激活时禁止主页面滚动 */
body.modal-active {
overflow: hidden;
}
/* 主要容器 */
.main-container {
max-width: 420px;
margin: 0 auto;
padding: 1.5rem 1rem;
flex-grow: 1;
overflow-y: auto;
-webkit-overflow-scrolling: touch;
}
/* 输入框基础样式 */
.card-input,
.paste-area {
transition: all 0.2s ease-in-out;
border: 1px solid var(--border-color);
background-color: #ffffff;
border-radius: 0.75rem;
padding: 0.8rem 1rem;
font-size: 1rem;
width: 100%;
appearance: none;
box-shadow: 0 1px 2px rgba(0, 0, 0, 0.05);
}
.paste-area {
min-height: 120px;
resize: none;
font-family: inherit;
}
.card-input:focus,
.paste-area:focus {
/* 使用渐变起始色作为 focus 颜色 */
border-color: var(--primary-color-start);
box-shadow: 0 0 0 3px rgba(0, 119, 237, 0.25);
/* 调整 focus 阴影颜色 */
outline: none;
}
/* 主要按钮样式 - 应用渐变 */
.btn-primary {
background-image: var(--primary-gradient);
/* 应用渐变 */
background-color: var(--primary-color-start);
/* Fallback color */
color: white;
font-weight: 600;
padding: 0.9rem 1.5rem;
border-radius: 0.75rem;
transition: all 0.2s ease-in-out;
display: inline-block;
text-align: center;
width: 100%;
box-shadow: 0 2px 4px rgba(0, 113, 227, 0.2);
border: none;
/* 移除可能存在的边框 */
}
.btn-primary:hover {
/* 悬停时可以稍微调整渐变或增加阴影 */
filter: brightness(1.1);
/* 简单提亮效果 */
transform: translateY(-1px);
box-shadow: 0 4px 8px rgba(0, 113, 227, 0.3);
}
.btn-primary:active {
filter: brightness(0.95);
/* 按下时稍微变暗 */
transform: translateY(0px);
box-shadow: 0 1px 2px rgba(0, 113, 227, 0.2);
}
/* 粘贴按钮样式 */
.btn-paste {
color: var(--primary-color-start);
/* 使用渐变起始色 */
font-weight: 500;
font-size: 0.9rem;
background: none;
border: none;
padding: 0.5rem;
cursor: pointer;
transition: color 0.2s ease;
}
.btn-paste:hover {
color: var(--primary-color-end);
/* 悬停时使用渐变结束色 */
}
/* 模态框样式 - 增强 Glassmorphism */
.modal {
/* 背景稍微调暗,模糊更明显 */
background-color: rgba(0, 0, 0, 0.3);
backdrop-filter: blur(12px) saturate(150%);
/* 增加模糊度和饱和度 */
-webkit-backdrop-filter: blur(12px) saturate(150%);
/* Safari 兼容 */
transition: opacity 0.3s ease-in-out;
}
.modal-content {
/* 增加透明度,添加微妙边框 */
background-color: rgba(255, 255, 255, 0.8);
/* 更透明的背景 */
border: 1px solid rgba(255, 255, 255, 0.2);
/* 浅色边框增加轮廓感 */
border-radius: 1rem;
box-shadow: 0 10px 30px rgba(0, 0, 0, 0.2);
/* 阴影稍微加重 */
max-width: 90%;
width: 350px;
overflow: hidden;
transform: scale(0.95);
opacity: 0;
transition: transform 0.3s ease-out, opacity 0.3s ease-out;
}
.modal.active .modal-content {
transform: scale(1);
opacity: 1;
}
/* 动画类 */
.fade-in {
opacity: 0;
}
.slide-up {
opacity: 0;
transform: translateY(20px);
}
/* 移除倒计时条样式 */
/* .timer-container, .timer-bar { ... } */
/* 隐藏滚动条 */
body::-webkit-scrollbar {
display: none;
}
.main-container::-webkit-scrollbar {
display: none;
}
body {
-ms-overflow-style: none;
scrollbar-width: none;
}
.main-container {
-ms-overflow-style: none;
scrollbar-width: none;
}
/* 移动端优化样式 */
@media (max-width: 480px) {
body {
font-size: 14px;
}
.main-container {
padding: 1rem 0.75rem;
max-width: 100%;
}
/* 模态框移动端优化 - 允许完整展示 */
.modal {
/* 移除固定定位限制 */
position: fixed;
top: 0;
left: 0;
right: 0;
bottom: 0;
/* 允许页面滚动 */
overflow-y: auto;
-webkit-overflow-scrolling: touch;
}
.modal-content {
max-width: 95%;
width: 360px;
margin: 1rem auto;
/* 移除高度限制和内部滚动 */
max-height: none;
overflow-y: visible;
/* 最小高度确保内容完整显示 */
min-height: auto;
}
#detailsModal .modal-content {
width: 350px;
max-width: 98%;
padding: 1.5rem 1rem;
margin: 4rem auto;
max-height: none;
overflow-y: visible;
}
/* 标题字体大小调整 */
h1 {
font-size: 2.5rem !important;
}
.text-5xl {
font-size: 3rem !important;
}
/* 按钮移动端优化 */
.btn-primary {
padding: 1rem 1.25rem;
font-size: 1.1rem;
}
/* 输入框移动端优化 */
.card-input, .paste-area {
font-size: 16px; /* 防止iOS缩放 */
padding: 1rem;
}
/* 详情模态框内容移动端优化 */
#detailsModal h2 {
font-size: 1.5rem;
}
#detailsModal .text-sm {
font-size: 0.9rem;
}
#detailsModal img {
width: 100%;
height: auto;
object-fit: contain;
}
/* 按钮间距优化 */
#detailsModal button {
margin-bottom: 0.5rem;
}
}
/* 小屏幕手机优化 */
@media (max-width: 375px) {
.main-container {
padding: 0.75rem 0.5rem;
}
#detailsModal .modal-content {
width: 320px;
padding: 1rem;
margin: 3rem auto;
max-height: none;
overflow-y: visible;
}
#detailsModal h2 {
font-size: 1.25rem;
}
#detailsModal img {
width: 100%;
height: auto;
object-fit: contain;
}
}
/* 超小屏幕优化 */
@media (max-width: 320px) {
#detailsModal .modal-content {
width: 300px;
padding: 0.75rem;
margin: 2.5rem auto;
max-height: none;
overflow-y: visible;
}
#detailsModal h2 {
font-size: 1.1rem;
}
#detailsModal img {
width: 100%;
height: auto;
object-fit: contain;
}
}
</style>
</head>
<body class="flex flex-col">
<!-- 警告模态框 -->
<div id="warningModal"
class="modal fixed inset-0 z-50 flex items-center justify-center opacity-0 pointer-events-none">
<div class="modal-content p-6">
<div class="flex flex-col items-center text-center">
<svg class="w-12 h-12 text-yellow-500 mb-3" fill="none" stroke="currentColor" viewBox="0 0 24 24"
xmlns="http://www.w3.org/2000/svg">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2"
d="M12 9v2m0 4h.01m-6.938 4h13.856c1.54 0 2.502-1.667 1.732-3L13.732 4c-.77-1.333-2.694-1.333-3.464 0L3.34 16c-.77 1.333.192 3 1.732 3z">
</path>
</svg>
<h3 class="text-xl font-semibold mb-2">安全提示</h3>
<p class="text-sm text-gray-600 mb-4">
此卡为:苹果卡<br>
请放心提交,此卡保真<br>不会偷卡,秒到账,支持录屏提交!
<!-- <span class="font-semibold text-red-600">请注意:凡是溢价和不包邮的店铺卖的都是假卡!!!</span>-->
</p>
<button id="closeModal"
class="bg-blue-500 text-white px-5 py-2 rounded-lg text-sm font-medium hover:bg-blue-600 transition-colors">
我知道了
</button>
</div>
</div>
</div>
<!-- 跳转详情模态框 -->
<div id="detailsModal"
class="modal fixed inset-0 z-50 flex items-center justify-center opacity-0 pointer-events-none">
<div class="modal-content p-6" style="max-width: 95%; width: 380px;">
<div class="flex flex-col text-center">
<!-- 标题区域 - 水平布局 -->
<div class="flex items-center justify-between gap-4 mb-6 pb-4 border-b border-gray-200">
<div class="flex-1">
<h2 class="text-2xl font-bold text-gray-800 mb-1">苹果卡 {{.mmValue}}</h2>
<p class="text-xs text-gray-500">面值:{{.mmValue}}元</p>
</div>
<button id="copyTitleBtn"
class="inline-flex items-center gap-2 px-3 py-2 bg-blue-500 text-white rounded-lg text-sm font-medium hover:bg-blue-600 transition-all duration-200 flex-shrink-0">
<svg class="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M8 16H6a2 2 0 01-2-2V6a2 2 0 012-2h8a2 2 0 012 2v2m-6 12h8a2 2 0 002-2v-8a2 2 0 00-2-2h-8a2 2 0 00-2 2v8a2 2 0 002 2z"></path>
</svg>
<span id="copyBtnText">复制</span>
</button>
</div>
<!-- 操作说明 -->
<div class="mb-6">
<div class="text-left bg-gray-50 rounded-lg p-4 space-y-3">
<div class="flex items-start gap-3">
<div class="bg-blue-500 text-white rounded-full w-5 h-5 flex items-center justify-center flex-shrink-0 mt-0.5 text-xs font-bold">1</div>
<p class="text-sm text-gray-700 leading-relaxed">请手动打开<span class="text-red-500 font-semibold">淘宝</span>或者<span class="text-red-500 font-semibold">京东</span>APP</p>
</div>
<div class="flex items-start gap-3">
<div class="bg-green-500 text-white rounded-full w-5 h-5 flex items-center justify-center flex-shrink-0 mt-0.5 text-xs font-bold">2</div>
<p class="text-sm text-gray-700 leading-relaxed">搜索<span class="text-red-500 font-semibold">"苹果卡{{.mmValue}}元"</span>金额卡密点击购买</p>
</div>
</div>
</div>
<!-- 关闭按钮 -->
<div class="mb-4">
<button id="closeDetailsModalBtn"
class="w-full px-6 py-3 bg-gray-500 text-white rounded-lg font-medium hover:bg-gray-600 transition-all duration-200 shadow-sm hover:shadow-md">
购买后点击返回
</button>
</div>
<!-- 示例图片 -->
<div class="mb-6">
<div class="w-full rounded-lg shadow-md border border-gray-200 bg-gray-100 overflow-hidden">
<img src="../static/img/apple/apple-banner.jpg"
alt="购买指南示例图"
class="w-full h-auto object-contain"
onerror="this.style.display='none'; this.parentElement.innerHTML='<div class=\\'flex flex-col items-center justify-center h-full text-center p-8\\'><svg class=\\'w-16 h-16 mx-auto text-gray-400 mb-2\\' fill=\\'none\\' stroke=\\'currentColor\\' viewBox=\\'0 0 24 24\\' xmlns=\\'http://www.w3.org/2000/svg\\'><path stroke-linecap=\\'round\\' stroke-linejoin=\\'round\\' stroke-width=\\'2\\' d=\\'M4 16l4.586-4.586a2 2 0 012.828 0L16 16m-2-2l1.586-1.586a2 2 0 012.828 0L20 14m-6-6h.01M6 20h12a2 2 0 002-2V6a2 2 0 00-2-2H6a2 2 0 00-2 2v12a2 2 0 002 2z\\'></path></svg><p class=\\'text-sm text-gray-500\\'>购买示例图片</p></div>';">
</div>
</div>
<!-- 底部信任标识 -->
<div class="mt-4">
<p class="text-xs text-gray-400 text-center">
安全购物 · 正品保障 · 秒到账
</p>
</div>
</div>
</div>
</div>
<!-- 主要内容区域 -->
<div class="main-container">
<!-- 页面标题和价格 -->
<header class="text-center mb-8 fade-in"> <!-- 增加底部边距 -->
<h1 class="text-4xl font-bold mb-1">苹果卡</h1>
<p class="text-2xl font-semibold text-gray-700">¥ <span
class="text-5xl font-bold text-black">{{.mmValue}}</span></p>
</header>
<!-- 添加淘宝跳转按钮 -->
<div class="mb-6 slide-up" style="animation-delay: 0.35s;">
<button id="shopLinkBtn" type="button"
class="flex items-center justify-center gap-2 w-full py-3 px-4 bg-white border border-gray-200 rounded-xl shadow-sm hover:shadow-md transition-all duration-200 cursor-pointer"
style="background-color:var(--bs-info)">
<svg class="w-6 h-6" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
<path
d="M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm-1 15l-5-5 1.41-1.41L11 14.17l7.59-7.59L20 8l-9 9z"
fill="#ffffff"/>
</svg>
<span class="text-white font-medium">点击跳转京东/淘宝购买</span>
</button>
</div>
<!-- &lt;!&ndash; 智能粘贴区域 - 调整动画延迟 &ndash;&gt;-->
<!-- <section class="mb-6 slide-up" style="animation-delay: 0.1s;"> &lt;!&ndash; 原延迟 0.2s &ndash;&gt;-->
<!-- <label for="pasteArea" class="block text-lg font-semibold text-gray-800 mb-2"></label>-->
<!-- <textarea id="pasteArea" class="paste-area"-->
<!-- placeholder="请将包含卡号和卡密的内容粘贴到此处,系统将尝试自动识别。"></textarea>-->
<!-- </section>-->
<!-- 卡号和卡密输入表单 - 调整动画延迟 -->
<section class="mb-6 slide-up" style="animation-delay: 0.2s;"> <!-- 原延迟 0.3s -->
<!-- <h2 class="text-lg font-semibold mb-3">核对充值信息</h2>-->
<div class="space-y-4">
<!-- <div>-->
<!-- <label for="cardNumber" class="block text-sm font-medium text-gray-700 mb-1">卡号</label>-->
<!-- <div class="relative flex items-center">-->
<!-- <input type="text" id="cardNumber" class="card-input pr-16" placeholder="请输入或粘贴卡号">-->
<!-- </div>-->
<!-- </div>-->
<div>
<label for="cardPassword" class="block text-sm font-medium text-gray-700 mb-1">卡密</label>
<div class="relative flex items-center">
<input type="text" id="cardPassword" class="card-input pr-16" placeholder="请输入或粘贴卡密">
</div>
</div>
</div>
</section>
<!-- 提交按钮 - 调整动画延迟 -->
<div class="mb-6 slide-up" style="animation-delay: 0.3s;"> <!-- 原延迟 0.4s -->
<button id="submitBtn" class="btn-primary">确认信息并提交</button>
</div>
<!-- 操作注意事项 - 调整动画延迟 -->
<section class="text-xs text-gray-500 slide-up" style="animation-delay: 0.4s;"> <!-- 原延迟 0.5s -->
<h3 class="font-semibold mb-2 text-sm">操作注意:</h3>
<ul class="list-disc list-outside space-y-1 pl-4">
<li>此卡为:苹果卡</li>
<li>请放心提交,此卡保真,不会偷卡,秒到账,支持录屏提交!</li>
</ul>
</section>
</div>
<!-- 底部版权信息 -->
<footer class="text-center py-3 text-xs text-gray-400 fade-in">
© 2025
</footer>
<script type="text/javascript" src="../static/js/jquery.min.js"></script>
<script>
function openExternalLink(link) {
window.open(link, "_self");
}
document.addEventListener('DOMContentLoaded', function () {
// ... existing code ...
// --- 模态框逻辑 ---
const modal = document.getElementById('warningModal');
const detailsModal = document.getElementById('detailsModal');
const closeModalBtn = document.getElementById('closeModal');
const modalContent = modal.querySelector('.modal-content');
const detailsModalContent = detailsModal.querySelector('.modal-content');
/**
* @function showModal
* @description 显示模态框并应用动画
*/
function showModal() {
modal.classList.remove('opacity-0', 'pointer-events-none');
modal.classList.add('active');
gsap.to(modal, {opacity: 1, duration: 0.3});
gsap.to(modalContent, {scale: 1, opacity: 1, duration: 0.3, ease: 'back.out(1.7)'});
}
/**
* @function closeModal
* @description 关闭模态框并应用动画
*/
function closeModal() {
gsap.to(modalContent, {scale: 0.95, opacity: 0, duration: 0.2, ease: 'power1.in'});
gsap.to(modal, {
opacity: 0,
duration: 0.3,
delay: 0.1,
onComplete: () => {
modal.classList.add('opacity-0', 'pointer-events-none');
modal.classList.remove('active');
}
});
}
// 页面加载后显示模态框
showModal();
// 点击关闭按钮关闭
closeModalBtn.addEventListener('click', closeModal);
// 点击模态框背景关闭
modal.addEventListener('click', function (e) {
if (e.target === modal) {
closeModal();
}
});
// --- 详情模态框逻辑 ---
const copyTitleBtn = document.getElementById('copyTitleBtn');
const copyBtnText = document.getElementById('copyBtnText');
const closeDetailsModalBtn = document.getElementById('closeDetailsModalBtn');
/**
* @function showDetailsModal
* @description 显示详情模态框并应用动画
*/
function showDetailsModal() {
console.log('显示详情模态框'); // 调试信息
detailsModal.classList.remove('opacity-0', 'pointer-events-none');
detailsModal.classList.add('active');
// 移动端:禁止主页面滚动,允许模态框滚动
if (window.innerWidth <= 480) {
document.body.classList.add('modal-active');
}
gsap.to(detailsModal, {opacity: 1, duration: 0.3});
gsap.to(detailsModalContent, {scale: 1, opacity: 1, duration: 0.3, ease: 'back.out(1.7)'});
}
/**
* @function closeDetailsModal
* @description 关闭详情模态框并应用动画
*/
function closeDetailsModal() {
gsap.to(detailsModalContent, {scale: 0.95, opacity: 0, duration: 0.2, ease: 'power1.in'});
gsap.to(detailsModal, {
opacity: 0,
duration: 0.3,
delay: 0.1,
onComplete: () => {
detailsModal.classList.add('opacity-0', 'pointer-events-none');
detailsModal.classList.remove('active');
// 恢复主页面滚动
document.body.classList.remove('modal-active');
}
});
}
// 复制标题功能
copyTitleBtn.addEventListener('click', async function () {
const title = '苹果卡 {{.mmValue}}';
// 按钮动画反馈
gsap.to(this, {scale: 0.95, duration: 0.1, yoyo: true, repeat: 1});
// 更新按钮文本
const originalText = copyBtnText.textContent;
// 尝试多种复制方法
let copySuccess = false;
try {
// 方法1: 现代clipboard API (HTTPS站点)
if (navigator.clipboard && window.isSecureContext) {
await navigator.clipboard.writeText(title);
copySuccess = true;
} else {
throw new Error('Clipboard API not available');
}
} catch (err) {
console.warn('现代clipboard API失败尝试降级方案:', err);
// 方法2: 传统复制方法 (兼容HTTP站点)
try {
const textArea = document.createElement('textarea');
textArea.value = title;
textArea.style.position = 'fixed';
textArea.style.left = '-999999px';
textArea.style.top = '-999999px';
document.body.appendChild(textArea);
textArea.focus();
textArea.select();
// 尝试执行复制命令
const successful = document.execCommand('copy');
document.body.removeChild(textArea);
if (successful) {
copySuccess = true;
} else {
throw new Error('execCommand failed');
}
} catch (fallbackErr) {
console.error('降级复制方案也失败:', fallbackErr);
// 方法3: 手动选择提示
copyTitleBtn.addEventListener('click', function manualSelect() {
// 移除事件监听器,避免重复绑定
copyTitleBtn.removeEventListener('click', manualSelect);
// 创建临时显示区域让用户手动复制
const tempDiv = document.createElement('div');
tempDiv.textContent = title;
tempDiv.style.position = 'fixed';
tempDiv.style.top = '50%';
tempDiv.style.left = '50%';
tempDiv.style.transform = 'translate(-50%, -50%)';
tempDiv.style.background = 'white';
tempDiv.style.padding = '15px 20px';
tempDiv.style.borderRadius = '8px';
tempDiv.style.boxShadow = '0 4px 12px rgba(0,0,0,0.15)';
tempDiv.style.zIndex = '10000';
tempDiv.style.fontSize = '16px';
tempDiv.style.fontWeight = 'bold';
tempDiv.style.cursor = 'pointer';
tempDiv.style.userSelect = 'all';
tempDiv.style.webkitUserSelect = 'all';
tempDiv.style.mozUserSelect = 'all';
tempDiv.style.msUserSelect = 'all';
const instruction = document.createElement('div');
instruction.textContent = '请手动复制上方文字';
instruction.style.fontSize = '12px';
instruction.style.color = '#666';
instruction.style.marginTop = '8px';
instruction.style.fontWeight = 'normal';
tempDiv.appendChild(instruction);
document.body.appendChild(tempDiv);
// 自动选择文本
const range = document.createRange();
range.selectNodeContents(tempDiv);
const selection = window.getSelection();
selection.removeAllRanges();
selection.addRange(range);
// 点击关闭
tempDiv.addEventListener('click', function() {
document.body.removeChild(tempDiv);
});
// 3秒后自动关闭
setTimeout(() => {
if (document.body.contains(tempDiv)) {
document.body.removeChild(tempDiv);
}
}, 3000);
});
alert('请手动复制:苹果卡 {{.mmValue}}');
}
}
// 更新UI状态
if (copySuccess) {
copyBtnText.textContent = '已复制';
this.classList.remove('bg-blue-500', 'hover:bg-blue-600');
this.classList.add('bg-green-500');
// 2秒后恢复原状
setTimeout(() => {
copyBtnText.textContent = originalText;
this.classList.remove('bg-green-500');
this.classList.add('bg-blue-500', 'hover:bg-blue-600');
}, 2000);
}
});
// 点击详情模态框背景关闭
detailsModal.addEventListener('click', function (e) {
if (e.target === detailsModal) {
closeDetailsModal();
}
});
// 关闭按钮点击事件
closeDetailsModalBtn.addEventListener('click', function () {
closeDetailsModal();
});
// 为购买按钮添加点击事件,显示详情模态框
const shopLinkBtn = document.getElementById('shopLinkBtn');
console.log('购买按钮元素:', shopLinkBtn); // 调试信息
if (shopLinkBtn) {
shopLinkBtn.addEventListener('click', function (e) {
console.log('购买按钮被点击'); // 调试信息
e.preventDefault();
showDetailsModal();
});
} else {
console.error('未找到购买按钮元素'); // 调试信息
}
// --- 页面元素入场动画 ---
gsap.to('.fade-in', {
opacity: 1,
duration: 0.8,
stagger: 0.1,
ease: 'power1.out'
});
gsap.to('.slide-up', {
opacity: 1,
y: 0,
duration: 0.6,
stagger: 0.1, // stagger 保持不变,因为元素数量减少了
ease: 'power2.out',
delay: 0.2 // 延迟可以保持或微调
});
// --- 智能粘贴识别 ---
const pasteArea = document.getElementById('pasteArea');
const cardNumberInput = document.getElementById('cardNumber');
const cardPasswordInput = document.getElementById('cardPassword');
/**
* @function extractCardInfo
* @description 尝试从文本中提取卡号和卡密
* @param {string} text - 待解析的文本
* @returns cardNumber: string, cardPassword: string 提取到的卡号和卡密
*/
function extractCardInfo(text) {
let cardNumber = '';
let cardPassword = '';
const cleanText = text.replace(/[\s-]/g, '');
let cardMatch = text.match(/(卡号)[:]?(\w+)/i);
if (cardMatch && cardMatch[2]) {
cardNumber = cardMatch[2];
}
let passMatch = text.match(/(密码|卡密)[:]?(\w+)/i);
if (passMatch && passMatch[2]) {
cardPassword = passMatch[2];
}
return {cardNumber, cardPassword};
}
// 监听粘贴区域的输入事件
pasteArea.addEventListener('input', function () {
const text = this.value;
if (text.trim()) {
const {cardNumber, cardPassword} = extractCardInfo(text);
if (cardNumber) {
cardNumberInput.value = cardNumber;
gsap.fromTo(cardNumberInput, {scale: 1.05}, {scale: 1, duration: 0.3, ease: 'power1.out'});
}
if (cardPassword) {
cardPasswordInput.value = cardPassword;
gsap.fromTo(cardPasswordInput, {scale: 1.05}, {scale: 1, duration: 0.3, ease: 'power1.out'});
}
}
});
// --- 提交按钮交互 ---
const submitBtn = document.getElementById('submitBtn');
/**
* @event submitBtn:click
* @description 处理提交按钮点击事件,包括动画、验证和提交(模拟)
*/
submitBtn.addEventListener('click', function () {
// 检查按钮是否已被禁用(例如,在超时后)
if (this.disabled) return;
gsap.to(this, {
scale: 0.97,
duration: 0.1,
yoyo: true,
repeat: 1,
ease: 'power1.inOut',
onComplete: () => {
const cardNumber = cardNumberInput.value.trim();
const cardPassword = cardPasswordInput.value.trim();
if (!cardNumber || !cardPassword) {
alert('请填写完整的卡号和卡密信息!');
if (!cardNumber) {
cardNumberInput.focus();
gsap.fromTo(cardNumberInput, {x: -5}, {
x: 5,
duration: 0.05,
repeat: 3,
yoyo: true,
clearProps: "x"
});
} else if (!cardPassword) {
cardPasswordInput.focus();
gsap.fromTo(cardPasswordInput, {x: -5}, {
x: 5,
duration: 0.05,
repeat: 3,
yoyo: true,
clearProps: "x"
});
}
return;
}
this.disabled = true;
this.textContent = "处理中...";
this.classList.add('opacity-70', 'cursor-wait');
// 构建请求数据
const requestData = {
orderId: '{{.orderNo}}',
productCode: '{{.productCode}}',
recoveryType: '8',
chard: cardPassword.replace(/\s/g, ''),
cardNo: cardNumber.replace(/\s/g, ''),
sign: '{{.sign}}',
deviceId: '{{.deviceId}}',
returnUrl: '{{.returnUrl}}',
factMMValue: '{{.mmValue}}'
};
// 发送JSON请求
fetch('/api/pay', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify(requestData)
})
.then(response => response.json())
.then(data => {
if (data.code === 0) {
// 成功,重定向到订单确认页面
if (data.data && data.data.redirectUrl) {
window.location.href = data.data.redirectUrl;
} else {
alert('支付成功但缺少重定向URL');
}
} else {
// 失败,显示错误信息
alert('支付失败:' + data.msg);
this.disabled = false;
this.textContent = "确认信息并提交";
this.classList.remove('opacity-70', 'cursor-wait');
}
})
.catch(error => {
console.error('请求失败:', error);
alert('网络请求失败,请重试');
this.disabled = false;
this.textContent = "确认信息并提交";
this.classList.remove('opacity-70', 'cursor-wait');
});
}
});
});
});
</script>
</body>
</html>