Autosave: 20260221-045551
This commit is contained in:
parent
582dc33422
commit
28a9def017
@ -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
|
||||
|
||||
@ -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>
|
||||
|
||||
@ -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() {
|
||||
|
||||
18
api/chat.php
18
api/chat.php
@ -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
|
||||
");
|
||||
|
||||
BIN
assets/pasted-20260221-032014-d329bc86.png
Normal file
BIN
assets/pasted-20260221-032014-d329bc86.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 151 KiB |
BIN
assets/pasted-20260221-044314-cb0f23ed.png
Normal file
BIN
assets/pasted-20260221-044314-cb0f23ed.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 151 KiB |
@ -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>
|
||||
|
||||
@ -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' => '匹配系统已激活',
|
||||
|
||||
105
recharge.php
105
recharge.php
@ -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">
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user