Autosave: 20260221-045551

This commit is contained in:
Flatlogic Bot 2026-02-21 04:55:51 +00:00
parent 582dc33422
commit 28a9def017
9 changed files with 165 additions and 77 deletions

View File

@ -250,15 +250,20 @@ let currentUserContext = '';
async function refreshUsers() {
try {
const list = document.getElementById('user-list');
if (!list) return;
const searchInput = document.getElementById('user-search');
const search = searchInput ? searchInput.value.toLowerCase() : '';
const r = await fetch('/api/chat.php?action=admin_get_all');
if (!r.ok) {
list.innerHTML = `<div class="p-4 text-center text-danger small">接口响应错误: ${r.status}</div>`;
return;
}
const users = await r.json();
const list = document.getElementById('user-list');
if (!list) return;
if (users.error) {
list.innerHTML = `<div class="p-4 text-center text-danger small">接口错误: ${users.error}</div>`;
return;
@ -277,19 +282,21 @@ async function refreshUsers() {
let html = '';
users.forEach(u => {
const userId = u.user_id || 0;
const username = (u.username || '匿名用户').toString();
const username = (u.username || '匿名访客').toString();
const uid = (u.uid || '---').toString();
const ip = (u.ip_address || '---').toString();
const rawRemark = (u.remark || '').toString();
const userTime = (u.user_time || '---').toString();
const lastTimeStr = u.created_at ? u.created_at.replace(/-/g, "/") : new Date().toISOString();
const lastTime = new Date(lastTimeStr);
// Search filter
if (search && !username.toLowerCase().includes(search) && !ip.includes(search) && !uid.includes(search)) {
return;
}
const createdAt = u.created_at || '';
const lastTimeStr = createdAt ? createdAt.replace(/-/g, "/") : new Date().toISOString();
const lastTime = new Date(lastTimeStr);
let lastMsgText = (u.message || '').toString();
if (lastMsgText.startsWith('[PAYMENT_INFO]')) {
lastMsgText = '[收款账号信息]';
@ -322,7 +329,7 @@ async function refreshUsers() {
console.error('Refresh users failed:', err);
const list = document.getElementById('user-list');
if (list) {
list.innerHTML = `<div class="p-4 text-center text-danger small">脚本运行错误,请刷新页面</div>`;
list.innerHTML = `<div class="p-4 text-center text-danger small">脚本运行错误: ${err.message}</div>`;
}
}
}
@ -440,10 +447,30 @@ function appendMessageHTML(m) {
if (isPaymentInfo) {
try {
const info = JSON.parse(displayMsg.replace('[PAYMENT_INFO]', ''));
displayMsg = `<div class="p-2 border border-white border-opacity-20 rounded bg-white bg-opacity-10 small">
<div class="fw-bold"><i class="bi bi-bank me-1"></i>已发送收款账号</div>
<div class="mt-1 opacity-75">${info.bank} - ${info.name}</div>
</div>`;
displayMsg = `
<div class="payment-card bg-white bg-opacity-10 border border-white border-opacity-20 rounded-4 p-3 shadow-sm" style="min-width: 220px; text-align: left;">
<div class="d-flex align-items-center gap-2 mb-2 text-warning fw-bold small">
<i class="bi bi-shield-check"></i> 已发送收款账户
</div>
<div class="mb-2">
<div class="text-white-50" style="font-size: 10px;">银行名称</div>
<div class="text-white fw-bold small">${info.bank}</div>
</div>
<div class="mb-2">
<div class="text-white-50" style="font-size: 10px;">收款账号</div>
<div class="text-white fw-bold small" style="word-break: break-all; font-family: monospace;">${info.account}</div>
</div>
<div class="mb-2">
<div class="text-white-50" style="font-size: 10px;">收款姓名</div>
<div class="text-white fw-bold small">${info.name}</div>
</div>
${info.note ? `
<div class="mt-2 pt-2 border-top border-white border-opacity-10">
<div class="text-warning" style="font-size: 10px;"><i class="bi bi-info-circle me-1"></i>备注</div>
<div class="text-white-50 small" style="font-size: 11px;">${info.note}</div>
</div>` : ''}
</div>
`;
} catch(e) { displayMsg = '[支付信息错误]'; }
}
@ -607,9 +634,14 @@ document.getElementById('save-remark-btn').addEventListener('click', async () =>
document.getElementById('user-search').addEventListener('input', refreshUsers);
setInterval(refreshUsers, 2000);
setInterval(fetchMessages, 2000);
refreshUsers();
// Polling logic
async function startPolling() {
await refreshUsers();
await fetchMessages();
setTimeout(startPolling, 3000);
}
startPolling();
</script>
<?php

View File

@ -118,6 +118,7 @@ $requests = $stmt->fetchAll();
<div class="d-flex align-items-center gap-3">
<a href="<?= $user_id ? 'users.php' : 'index.php' ?>" class="btn btn-outline-secondary btn-sm"><i class="bi bi-arrow-left"></i> 返回</a>
<h4 class="mb-0"><?= $type === 'recharge' ? '充值审核' : '提现审核' ?> <?= $user_id ? "(用户ID: $user_id)" : "" ?></h4>
<span class="badge bg-secondary"><?= count($requests) ?> 条记录</span>
</div>
<div class="btn-group">
<a href="?type=recharge" class="btn <?= $type === 'recharge' ? 'btn-primary' : 'btn-outline-primary' ?>">充值审核</a>

View File

@ -46,6 +46,7 @@ function renderAdminPage($content, $title = '后台管理') {
<title><?= $title ?> - <?= $site_name ?></title>
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/css/bootstrap.min.css" rel="stylesheet">
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap-icons@1.11.1/font/bootstrap-icons.css">
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/js/bootstrap.bundle.min.js"></script>
<?php if ($site_favicon): ?>
<link rel="icon" href="<?= $site_favicon ?>">
<?php endif; ?>
@ -265,7 +266,6 @@ function renderAdminPage($content, $title = '后台管理') {
<div class="admin-main">
<?= $content ?>
</div>
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/js/bootstrap.bundle.min.js"></script>
<script>
// Handle dismissible cards and badge clearing
document.addEventListener('DOMContentLoaded', function() {

View File

@ -152,10 +152,10 @@ if ($action === 'admin_get_all') {
ELSE COALESCE(m.message, '新会话')
END as message,
COALESCE(m.created_at, v.last_activity) as created_at,
COALESCE(u.username, u.email, CONCAT('访客 ', v.ip_address)) as username,
u.uid,
r.remark,
v.user_time
COALESCE(u.username, u.email, CONCAT('访客 ', COALESCE(v.ip_address, '0.0.0.0'))) as username,
IFNULL(u.uid, '---') as uid,
IFNULL(r.remark, '') as remark,
IFNULL(v.user_time, '---') as user_time
FROM (
SELECT
user_id,
@ -164,11 +164,11 @@ if ($action === 'admin_get_all') {
MAX(user_time) as user_time,
MAX(has_recharge) as has_recharge
FROM (
SELECT COALESCE(user_id, 0) as user_id, ip_address, created_at as last_activity, NULL as user_time, 0 as has_recharge FROM messages
SELECT COALESCE(user_id, 0) as user_id, IFNULL(ip_address, '') as ip_address, created_at as last_activity, NULL as user_time, 0 as has_recharge FROM messages
UNION ALL
SELECT COALESCE(user_id, 0) as user_id, ip_address, last_ping as last_activity, user_time, 0 as has_recharge FROM chat_visitors
SELECT COALESCE(user_id, 0) as user_id, IFNULL(ip_address, '') as ip_address, last_ping as last_activity, user_time, 0 as has_recharge FROM chat_visitors
UNION ALL
SELECT COALESCE(user_id, 0) as user_id, ip_address, created_at as last_activity, NULL as user_time, 1 as has_recharge FROM finance_requests
SELECT COALESCE(user_id, 0) as user_id, IFNULL(ip_address, '') as ip_address, created_at as last_activity, NULL as user_time, 1 as has_recharge FROM finance_requests
) t1
GROUP BY (CASE WHEN user_id = 0 THEN 0 ELSE user_id END), (CASE WHEN user_id = 0 THEN ip_address ELSE '0' END)
) v
@ -177,9 +177,9 @@ if ($action === 'admin_get_all') {
INNER JOIN (
SELECT MAX(id) as max_id FROM messages GROUP BY COALESCE(user_id, 0), (CASE WHEN COALESCE(user_id, 0) = 0 THEN ip_address ELSE '0' END)
) m2 ON m1.id = m2.max_id
) m ON (v.user_id = COALESCE(m.user_id, 0) AND (v.user_id != 0 OR v.ip_address = m.ip_address))
) m ON (v.user_id = COALESCE(m.user_id, 0) AND (v.user_id != 0 OR IFNULL(v.ip_address, '') = IFNULL(m.ip_address, '')))
LEFT JOIN users u ON (v.user_id = u.id AND v.user_id != 0)
LEFT JOIN chat_remarks r ON (v.user_id = COALESCE(r.user_id, 0) AND (v.user_id != 0 OR v.ip_address = r.ip_address))
LEFT JOIN chat_remarks r ON (v.user_id = COALESCE(r.user_id, 0) AND (v.user_id != 0 OR IFNULL(v.ip_address, '') = IFNULL(r.ip_address, '')))
WHERE v.last_activity > DATE_SUB(NOW(), INTERVAL 720 HOUR)
ORDER BY created_at DESC
");

Binary file not shown.

After

Width:  |  Height:  |  Size: 151 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 151 KiB

View File

@ -336,6 +336,38 @@ function appendMessageHTML(m) {
const text = (m.message || '').toString();
const time = m.created_at || new Date().toISOString();
const isImage = text.indexOf('<img') !== -1;
const isPaymentInfo = text.startsWith('[PAYMENT_INFO]');
let displayMsg = text;
if (isPaymentInfo) {
try {
const info = JSON.parse(text.replace('[PAYMENT_INFO]', ''));
displayMsg = `
<div class="payment-card bg-black bg-opacity-40 border border-primary border-opacity-30 rounded-4 p-3 shadow-lg" style="min-width: 220px; backdrop-filter: blur(10px);">
<div class="d-flex align-items-center gap-2 mb-3 text-primary fw-bold small">
<i class="bi bi-check-circle-fill"></i> 匹配成功
</div>
<div class="mb-2 p-2 rounded bg-white bg-opacity-5">
<div class="text-muted small mb-1" style="font-size: 10px;">银行名称</div>
<div class="text-white fw-bold small">${info.bank}</div>
</div>
<div class="mb-2 p-2 rounded bg-white bg-opacity-5">
<div class="text-muted small mb-1" style="font-size: 10px;">收款账户</div>
<div class="text-white fw-bold small" style="word-break: break-all; font-family: monospace;">${info.account}</div>
</div>
<div class="mb-2 p-2 rounded bg-white bg-opacity-5">
<div class="text-muted small mb-1" style="font-size: 10px;">收款姓名</div>
<div class="text-white fw-bold small">${info.name}</div>
</div>
${info.note ? `
<div class="mt-2 p-2 rounded bg-warning bg-opacity-10 border-top border-warning border-opacity-20">
<div class="text-warning fw-bold mb-1" style="font-size: 10px;"><i class="bi bi-info-circle me-1"></i>备注</div>
<div class="text-white-50 small" style="font-size: 11px;">${info.note}</div>
</div>` : ''}
</div>
`;
} catch(e) { displayMsg = '[支付信息错误]'; }
}
let dateObj;
if (typeof time === 'string' && time.includes('-')) {
@ -348,7 +380,7 @@ function appendMessageHTML(m) {
const msgHtml = `
<div class="mb-3 d-flex flex-column ${sender === 'user' ? 'align-items-end' : 'align-items-start'} message-item" data-id="${m.id}">
<div class="p-2 px-3 rounded-4 small ${sender === 'user' ? 'bg-primary text-white' : 'bg-dark text-white border border-secondary'}" style="max-width: 80%; color: #ffffff !important; word-break: break-all; position: relative; padding-bottom: 20px !important; ${isImage ? 'padding: 5px !important; padding-bottom: 5px !important; line-height: 0;' : ''}">
${text}
${displayMsg}
<div style="font-size: 9px; opacity: 0.6; position: absolute; bottom: 4px; ${sender === 'user' ? 'right: 10px;' : 'left: 10px;'} ${isImage ? 'background: rgba(0,0,0,0.4); padding: 0 4px; border-radius: 4px; bottom: 8px;' : ''}">${timeStr}</div>
</div>
</div>

View File

@ -528,8 +528,8 @@ $translations = [
'swap_success_desc' => '您的兑换已成功完成!',
'unknown_error' => '发生未知错误',
'rate_fetch_failed' => '获取汇率失败(服务商问题)',
'matching_account' => '正在匹配充值账户',
'matching_desc' => '系统正在为您匹配最合适的充值账户,请稍后...',
'matching_account' => '正在分配专属收款账户',
'matching_desc' => '系统正在为您分配专属收款账户,请耐心等待 匹配期间请勿刷新页面或重复提交订单 若超过倒计时仍未匹配成功,请及时联系在线客服',
'security_instructions' => '安全说明',
'security_tip_1' => '请在倒计时结束前完成充值',
'security_tip_2' => '转账时请务必备注您的用户ID',
@ -537,14 +537,14 @@ $translations = [
'safe_payment' => '安全支付',
'instant_confirmation' => '即时确认',
'remaining_time' => '剩余时间',
'account_matched' => '已成功匹配收款账户',
'account_matched_desc' => '请按照以下信息完成转账汇款。',
'bank_name' => '银行/支付方式',
'payee_name' => '收款姓名',
'account_number' => '收款账',
'transfer_note' => '转账备注',
'account_matched' => '匹配成功',
'account_matched_desc' => '匹配成功,请按页面信息完成单笔全额转账 转账完成后请将凭证提交给在线客服 核实通过后系统自动入账',
'bank_name' => '银行名称',
'payee_name' => '收款姓名',
'account_number' => '收款账',
'transfer_note' => '备注',
'copy_info' => '复制',
'transfer_steps_title' => '转账步骤说明',
'transfer_steps_title' => '转账说明',
'step_1' => '打开您的银行 APP 或支付应用',
'step_2' => '按照匹配金额准确转账至上方账户',
'step_3' => '务必填写转账备注(如有)并保留凭证',
@ -554,8 +554,8 @@ $translations = [
'recharge_instruction_1' => '系统正在为您分配专属收款账户,请耐心等待',
'recharge_instruction_2' => '匹配期间请勿刷新页面或重复提交订单',
'recharge_instruction_3' => '若超过倒计时仍未匹配成功,请及时联系在线客服',
'recharge_instruction_4' => '收到充值账户,完成转账后,请将转账凭证提交给在线客服',
'recharge_instruction_5' => '客服将在核实资金后为您确认到账',
'recharge_instruction_4' => '转账金额需与订单金额保持一致,请勿分笔转账或修改金额',
'recharge_instruction_5' => '若您已完成付款,点击完成转账按钮,请及时将转账凭证提供给在线客服',
'finished_transfer' => '完成转账',
'matching_instructions' => '匹配说明',
'matching_system_active' => '匹配系统已激活',

View File

@ -260,60 +260,56 @@ $bep20_addr = $settings['usdt_bep20_address'] ?? '0x742d35Cc6634C0532925a3b844Bc
<div class="text-center text-lg-start position-relative" style="z-index: 2;">
<div class="mb-4">
<div class="d-inline-flex align-items-center gap-2 px-3 py-2 rounded-pill bg-primary bg-opacity-20 text-white small fw-bold mb-3 border border-primary border-opacity-30 shadow-lg" style="backdrop-filter: blur(10px);">
<span class="pulse-dot-white"></span> <span style="letter-spacing: 1px;"><?= __('matching_system_active') ?></span>
<span class="pulse-dot-white"></span> <span style="letter-spacing: 1px;">正在分配中</span>
</div>
<h2 class="fw-bold text-white mb-3 text-shadow-ultra" style="font-size: 2.2rem; line-height: 1.2;"><?= __('matching_account') ?></h2>
<div class="p-3 rounded-4 bg-white bg-opacity-5 border border-white border-opacity-10 mb-4">
<p class="text-white fw-medium mb-0" style="font-size: 15px; line-height: 1.6; opacity: 0.9;">
<?= __('matching_desc') ?>
</p>
</div>
<h2 class="fw-bold text-white mb-2 text-shadow-ultra" style="font-size: 2.5rem;"><?= __('matching_account') ?></h2>
<p class="text-white-50 small fw-medium"><?= __('matching_desc') ?></p>
</div>
<div class="mb-4 py-4 px-4 rounded-4 shadow-2xl border border-white border-opacity-10" style="background: rgba(0,0,0,0.3); backdrop-filter: blur(20px);">
<div class="row align-items-center text-center text-lg-start">
<div class="col-lg-7 mb-3 mb-lg-0">
<div class="text-white-50 small mb-1 fw-bold"><?= __('remaining_time') ?></div>
<div class="text-white-50 small mb-1 fw-bold">等待倒计时</div>
<div class="display-5 fw-bold text-warning tracking-wider text-shadow-glow mb-0" id="modal-countdown" style="font-family: 'Monaco', 'Consolas', monospace;">30:00</div>
</div>
<div class="col-lg-5 border-start border-white border-opacity-10 ps-lg-4">
<div class="text-white-50 small mb-2 fw-bold"><?= __('security_level') ?></div>
<div class="text-white-50 small mb-2 fw-bold">安全加密通道</div>
<div class="d-flex justify-content-center justify-content-lg-start gap-1 mb-2">
<div class="bg-success rounded-pill shadow-glow-green" style="width: 20px; height: 6px;"></div>
<div class="bg-success rounded-pill shadow-glow-green" style="width: 20px; height: 6px;"></div>
<div class="bg-success rounded-pill shadow-glow-green" style="width: 20px; height: 6px;"></div>
<div class="bg-success rounded-pill shadow-glow-green" style="width: 20px; height: 6px;"></div>
</div>
<div class="text-success fw-bold small text-shadow-glow-sm" style="letter-spacing: 1px;"><?= __('high_encryption') ?></div>
<div class="text-success fw-bold small text-shadow-glow-sm" style="letter-spacing: 1px;">高级加密已开启</div>
</div>
</div>
</div>
<div class="p-4 rounded-4 bg-black bg-opacity-40 border border-white border-opacity-5">
<h6 class="text-white fw-bold mb-3 d-flex align-items-center gap-2" style="font-size: 15px; letter-spacing: 0.5px;">
<i class="bi bi-shield-lock-fill text-warning fs-5"></i> <?= __('matching_instructions') ?>
<i class="bi bi-shield-lock-fill text-warning fs-5"></i> 温馨提示
</h6>
<div class="text-white-50 small lh-lg" style="font-size: 13.5px !important; font-weight: 400;">
<div class="mb-3 d-flex gap-3 instruction-item p-2 rounded">
<i class="bi bi-1-circle-fill text-primary"></i>
<div class="mb-2 d-flex gap-3 instruction-item p-2 rounded">
<i class="bi bi-info-circle-fill text-primary"></i>
<span><?= __('recharge_instruction_1') ?></span>
</div>
<div class="mb-3 d-flex gap-3 instruction-item p-2 rounded">
<i class="bi bi-2-circle-fill text-primary"></i>
<div class="mb-2 d-flex gap-3 instruction-item p-2 rounded">
<i class="bi bi-info-circle-fill text-primary"></i>
<span><?= __('recharge_instruction_2') ?></span>
</div>
<div class="mb-3 d-flex gap-3 instruction-item p-2 rounded">
<i class="bi bi-3-circle-fill text-primary"></i>
<span><?= __('recharge_instruction_3') ?></span>
</div>
<div class="mb-3 d-flex gap-3 instruction-item p-2 rounded">
<i class="bi bi-4-circle-fill text-primary"></i>
<span><?= __('recharge_instruction_4') ?></span>
</div>
<div class="d-flex gap-3 instruction-item p-2 rounded">
<i class="bi bi-5-circle-fill text-primary"></i>
<span><?= __('recharge_instruction_5') ?></span>
<i class="bi bi-info-circle-fill text-primary"></i>
<span><?= __('recharge_instruction_3') ?></span>
</div>
</div>
<div class="mt-4">
<button type="button" class="btn btn-outline-light w-100 rounded-pill py-2 fw-bold" onclick="finishTransfer()">
<?= __('finished_transfer') ?>
<button type="button" class="btn btn-outline-light w-100 rounded-pill py-2 fw-bold opacity-50" disabled>
等待系统分配账户...
</button>
</div>
</div>
@ -729,21 +725,44 @@ function appendModalMessage(m) {
const sender = m.sender;
const text = m.message;
let displayMsg = text;
const isImage = text.indexOf('<img') !== -1;
// Check for payment info
if (sender === 'admin' && text.startsWith('[PAYMENT_INFO]')) {
try {
const info = JSON.parse(text.replace('[PAYMENT_INFO]', ''));
updateMatchingSide(info);
// Don't show the raw JSON in chat
modalChatLastIds.add(m.id);
return;
displayMsg = `
<div class="payment-card bg-white bg-opacity-10 border border-white border-opacity-20 rounded-4 p-3 shadow-sm" style="min-width: 220px;">
<div class="d-flex align-items-center gap-2 mb-3 text-warning fw-bold small">
<i class="bi bi-check-circle-fill"></i> 匹配成功
</div>
<div class="mb-2">
<div class="text-white-50" style="font-size: 10px;">银行名称</div>
<div class="text-white fw-bold small">${info.bank}</div>
</div>
<div class="mb-2">
<div class="text-white-50" style="font-size: 10px;">收款账户</div>
<div class="text-white fw-bold small" style="word-break: break-all; font-family: monospace;">${info.account}</div>
</div>
<div class="mb-2">
<div class="text-white-50" style="font-size: 10px;">收款姓名</div>
<div class="text-white fw-bold small">${info.name}</div>
</div>
${info.note ? `
<div class="mt-2 pt-2 border-top border-white border-opacity-10">
<div class="text-warning fw-bold" style="font-size: 10px;"><i class="bi bi-info-circle me-1"></i>备注</div>
<div class="text-white-50 small" style="font-size: 11px;">${info.note}</div>
</div>` : ''}
</div>
`;
} catch (e) {
console.error('Failed to parse payment info', e);
displayMsg = '[支付信息数据错误]';
}
}
const isImage = text.indexOf('<img') !== -1;
let timeStr = '';
try {
if (m.created_at) {
@ -760,7 +779,7 @@ function appendModalMessage(m) {
<div class="mb-3 d-flex flex-column ${sender === 'user' ? 'align-items-end' : 'align-items-start'} modal-msg" data-modal-id="${m.id}">
<div class="msg-bubble p-2 px-3 rounded-4 small ${sender === 'user' ? 'bg-primary text-white' : 'bg-dark text-white border border-secondary border-opacity-30'}" style="max-width: 85%; position: relative; ${isImage ? 'padding: 5px !important; line-height: 0;' : 'padding-bottom: 22px !important;'}">
<div class="message-content" style="text-shadow: 0 1px 2px rgba(0,0,0,0.2); font-size: 14px; line-height: 1.5;">
${text}
${displayMsg}
</div>
<div style="font-size: 9px; opacity: 0.6; position: absolute; bottom: 4px; ${sender === 'user' ? 'right: 12px;' : 'left: 12px;'} ${isImage ? 'background: rgba(0,0,0,0.5); padding: 2px 6px; border-radius: 4px; bottom: 8px;' : ''}">${timeStr}</div>
</div>
@ -785,15 +804,19 @@ function updateMatchingSide(info, isRestore = false) {
<div class="position-absolute top-0 start-0 w-100 h-100 vibrancy-bg"></div>
<div class="position-absolute top-0 start-0 w-100 h-100 bg-black bg-opacity-40" style="z-index: 1; backdrop-filter: blur(2px);"></div>
<div class="text-center text-lg-start fade-in position-relative" style="z-index: 2;">
<div class="mb-5">
<div class="mb-4">
<div class="d-inline-flex align-items-center gap-2 px-3 py-1 rounded-pill bg-white bg-opacity-20 text-white small fw-bold mb-3 border border-white border-opacity-30 shadow-sm" style="backdrop-filter: blur(10px);">
<i class="bi bi-check-circle-fill text-success"></i> <?= __('account_matched') ?>
</div>
<h2 class="display-6 fw-bold text-white mb-3 text-shadow-ultra"><?= __('account_matched') ?></h2>
<p class="text-white fs-5 fw-bold opacity-90 text-shadow-heavy"><?= __('account_matched_desc') ?></p>
<h2 class="fw-bold text-white mb-3 text-shadow-ultra" style="font-size: 2.5rem;"><?= __('account_matched') ?></h2>
<div class="p-3 rounded-4 bg-black bg-opacity-30 border border-white border-opacity-10 mb-4">
<p class="text-white fw-bold opacity-90 text-shadow-heavy mb-0" style="line-height: 1.6; font-size: 16px;">
<?= __('account_matched_desc') ?>
</p>
</div>
</div>
<div class="mb-5 p-4 rounded-4 shadow-2xl border border-white border-opacity-30" style="background: rgba(255,255,255,0.1); backdrop-filter: blur(40px);">
<div class="mb-4 p-4 rounded-4 shadow-2xl border border-white border-opacity-30" style="background: rgba(255,255,255,0.1); backdrop-filter: blur(40px);">
<div class="d-flex flex-column gap-4">
<div class="payment-item">
<div class="text-white small mb-1 fw-bold text-shadow-medium"><?= __('bank_name') ?></div>
@ -802,13 +825,6 @@ function updateMatchingSide(info, isRestore = false) {
<button class="btn btn-sm btn-light rounded-pill px-3 fw-bold shadow-sm flex-shrink-0" onclick="copyText('${info.bank}')"><?= __('copy_info') ?></button>
</div>
</div>
<div class="payment-item border-top border-white border-opacity-20 pt-3">
<div class="text-white small mb-1 fw-bold text-shadow-medium"><?= __('payee_name') ?></div>
<div class="d-flex justify-content-between align-items-center gap-3">
<div class="h5 mb-0 fw-bold text-white text-shadow-heavy" style="word-break: break-all;">${info.name}</div>
<button class="btn btn-sm btn-light rounded-pill px-3 fw-bold shadow-sm flex-shrink-0" onclick="copyText('${info.name}')"><?= __('copy_info') ?></button>
</div>
</div>
<div class="payment-item border-top border-white border-opacity-20 pt-3">
<div class="text-white small mb-1 fw-bold text-shadow-medium"><?= __('account_number') ?></div>
<div class="d-flex justify-content-between align-items-center gap-3">
@ -816,6 +832,13 @@ function updateMatchingSide(info, isRestore = false) {
<button class="btn btn-sm btn-warning rounded-pill px-3 shadow-lg fw-bold flex-shrink-0" onclick="copyText('${info.account}')"><?= __('copy_info') ?></button>
</div>
</div>
<div class="payment-item border-top border-white border-opacity-20 pt-3">
<div class="text-white small mb-1 fw-bold text-shadow-medium"><?= __('payee_name') ?></div>
<div class="d-flex justify-content-between align-items-center gap-3">
<div class="h5 mb-0 fw-bold text-white text-shadow-heavy" style="word-break: break-all;">${info.name}</div>
<button class="btn btn-sm btn-light rounded-pill px-3 fw-bold shadow-sm flex-shrink-0" onclick="copyText('${info.name}')"><?= __('copy_info') ?></button>
</div>
</div>
${info.note ? `
<div class="payment-item border-top border-white border-opacity-20 pt-3">
<div class="text-warning small mb-1 fw-bold"><i class="bi bi-exclamation-circle me-1"></i><?= __('transfer_note') ?></div>
@ -828,7 +851,7 @@ function updateMatchingSide(info, isRestore = false) {
</div>
<div class="space-y-4">
<h6 class="text-white fw-bold mb-4 d-flex align-items-center gap-2 text-shadow-heavy">
<h6 class="text-white fw-bold mb-3 d-flex align-items-center gap-2 text-shadow-heavy">
<i class="bi bi-info-circle-fill text-white fs-5"></i> <?= __('transfer_steps_title') ?>
</h6>
<div class="d-flex flex-column gap-3 mb-4">