经理中心
This commit is contained in:
parent
d82aec3805
commit
c39b9dc240
67
h5/admin-center/index.back.html
Normal file
67
h5/admin-center/index.back.html
Normal file
@ -0,0 +1,67 @@
|
||||
<!doctype html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no, viewport-fit=cover" />
|
||||
<title>Admin Center</title>
|
||||
<link rel="stylesheet" href="../center-static/center-static.css" />
|
||||
</head>
|
||||
<body>
|
||||
<div class="center-page">
|
||||
<header class="page-header">
|
||||
<button class="icon-button" type="button" data-action="back" aria-label="Back"><span>‹</span></button>
|
||||
<h1 id="pageTitle">Admin Center</h1>
|
||||
<button class="language-button" type="button" data-action="language">EN</button>
|
||||
</header>
|
||||
<main class="content">
|
||||
<section class="surface-card hero-card">
|
||||
<div class="hero-row">
|
||||
<div class="hero-title" id="heroTitle">My available salary</div>
|
||||
<button class="hero-link" id="heroLink" type="button">Details</button>
|
||||
</div>
|
||||
<div class="hero-value" id="heroValue">$0</div>
|
||||
</section>
|
||||
<section class="summary-grid" id="summaryGrid"></section>
|
||||
<div id="sections"></div>
|
||||
</main>
|
||||
<div class="toast" id="toast" hidden></div>
|
||||
</div>
|
||||
<script>
|
||||
window.CENTER_PAGE = {
|
||||
title: "Admin Center",
|
||||
identity: "ADMIN",
|
||||
heroTitle: "My available salary",
|
||||
heroLink: "Available income",
|
||||
heroRoute: "/available-income",
|
||||
balanceType: "ADMIN_SALARY",
|
||||
summaries: [
|
||||
{ label: "Role", value: "Admin" },
|
||||
{ label: "Scope", value: "BD / Agency" }
|
||||
],
|
||||
sections: [
|
||||
{
|
||||
title: "Operations",
|
||||
items: [
|
||||
{ label: "Item distribution", route: "/item-distribution", icon: "I" },
|
||||
{ label: "Admin policy", route: "/admin-policy", icon: "P" }
|
||||
]
|
||||
},
|
||||
{
|
||||
title: "Teams",
|
||||
items: [
|
||||
{ label: "Invite BD Leader", route: "/invite-bd-leader", icon: "+" },
|
||||
{ label: "My BD Leader teams", route: "/my-BDLeader-teams", icon: "L" },
|
||||
{ label: "Invite BD", route: "/invite-bd", icon: "+" },
|
||||
{ label: "My BD teams", route: "/my-BD-teams", icon: "B" },
|
||||
{ label: "Invite Agency", route: "/invite-agency", icon: "+" },
|
||||
{ label: "My Agency teams", route: "/my-agency-teams", icon: "A" },
|
||||
{ label: "Invite Recharge Agency", route: "/invite-recharge-agency", icon: "+" },
|
||||
{ label: "My Recharge Agency", route: "/my-recharge-agency", icon: "R" }
|
||||
]
|
||||
}
|
||||
]
|
||||
};
|
||||
</script>
|
||||
<script src="../center-static/center-static.js"></script>
|
||||
</body>
|
||||
</html>
|
||||
@ -1,67 +1,19 @@
|
||||
<!doctype html>
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no, viewport-fit=cover" />
|
||||
<title>Admin Center</title>
|
||||
<link rel="stylesheet" href="../center-static/center-static.css" />
|
||||
</head>
|
||||
<body>
|
||||
<div class="center-page">
|
||||
<header class="page-header">
|
||||
<button class="icon-button" type="button" data-action="back" aria-label="Back"><span>‹</span></button>
|
||||
<h1 id="pageTitle">Admin Center</h1>
|
||||
<button class="language-button" type="button" data-action="language">EN</button>
|
||||
</header>
|
||||
<main class="content">
|
||||
<section class="surface-card hero-card">
|
||||
<div class="hero-row">
|
||||
<div class="hero-title" id="heroTitle">My available salary</div>
|
||||
<button class="hero-link" id="heroLink" type="button">Details</button>
|
||||
</div>
|
||||
<div class="hero-value" id="heroValue">$0</div>
|
||||
</section>
|
||||
<section class="summary-grid" id="summaryGrid"></section>
|
||||
<div id="sections"></div>
|
||||
</main>
|
||||
<div class="toast" id="toast" hidden></div>
|
||||
</div>
|
||||
<script>
|
||||
window.CENTER_PAGE = {
|
||||
title: "Admin Center",
|
||||
identity: "ADMIN",
|
||||
heroTitle: "My available salary",
|
||||
heroLink: "Available income",
|
||||
heroRoute: "/available-income",
|
||||
balanceType: "ADMIN_SALARY",
|
||||
summaries: [
|
||||
{ label: "Role", value: "Admin" },
|
||||
{ label: "Scope", value: "BD / Agency" }
|
||||
],
|
||||
sections: [
|
||||
{
|
||||
title: "Operations",
|
||||
items: [
|
||||
{ label: "Item distribution", route: "/item-distribution", icon: "I" },
|
||||
{ label: "Admin policy", route: "/admin-policy", icon: "P" }
|
||||
]
|
||||
},
|
||||
{
|
||||
title: "Teams",
|
||||
items: [
|
||||
{ label: "Invite BD Leader", route: "/invite-bd-leader", icon: "+" },
|
||||
{ label: "My BD Leader teams", route: "/my-BDLeader-teams", icon: "L" },
|
||||
{ label: "Invite BD", route: "/invite-bd", icon: "+" },
|
||||
{ label: "My BD teams", route: "/my-BD-teams", icon: "B" },
|
||||
{ label: "Invite Agency", route: "/invite-agency", icon: "+" },
|
||||
{ label: "My Agency teams", route: "/my-agency-teams", icon: "A" },
|
||||
{ label: "Invite Recharge Agency", route: "/invite-recharge-agency", icon: "+" },
|
||||
{ label: "My Recharge Agency", route: "/my-recharge-agency", icon: "R" }
|
||||
]
|
||||
}
|
||||
]
|
||||
};
|
||||
</script>
|
||||
<script src="../center-static/center-static.js"></script>
|
||||
</body>
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>Document</title>
|
||||
</head>
|
||||
<body>
|
||||
<script>
|
||||
var target = new URL("https://h5.haiyihy.com/hyapp/manager-center/index.html")
|
||||
var source = new URL(window.location.href)
|
||||
source.searchParams.forEach(function (value, key) {
|
||||
target.searchParams.set(key, value)
|
||||
})
|
||||
target.searchParams.set("h5v", "20260507-1726")
|
||||
window.location.replace(target.toString())
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
@ -4,7 +4,7 @@
|
||||
<meta charset="UTF-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no, viewport-fit=cover" />
|
||||
<title>Manager Center</title>
|
||||
<link rel="stylesheet" href="./style.css?v=20260511-0107" />
|
||||
<link rel="stylesheet" href="./style.css?v=20260511-0109" />
|
||||
</head>
|
||||
<body>
|
||||
<div class="manager-center" aria-label="Manager Center" data-i18n-aria="page_label" data-loading="true">
|
||||
@ -65,55 +65,140 @@
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section class="card gift-card">
|
||||
<div class="section-head">
|
||||
<h2 data-i18n="gift_props">Gift Props</h2>
|
||||
</div>
|
||||
<label class="field-label" id="propsTypeLabelText" data-i18n="gift_type">Gift Type</label>
|
||||
<div class="custom-select" id="propsTypeSelect" data-value="RIDE">
|
||||
<button
|
||||
class="custom-select-button"
|
||||
id="propsTypeButton"
|
||||
type="button"
|
||||
aria-expanded="false"
|
||||
aria-haspopup="listbox"
|
||||
aria-labelledby="propsTypeLabelText propsTypeSelectedLabel"
|
||||
>
|
||||
<span id="propsTypeSelectedLabel">Ride</span>
|
||||
<svg viewBox="0 0 24 24" aria-hidden="true">
|
||||
<path d="m7 9 5 5 5-5" />
|
||||
<section class="card action-card" id="actionCard" hidden>
|
||||
<button class="action-item" id="giftEntryButton" type="button">
|
||||
<span class="action-item-icon" aria-hidden="true">
|
||||
<svg viewBox="0 0 24 24">
|
||||
<path d="M20 12v8H4v-8" />
|
||||
<path d="M2 7h20v5H2z" />
|
||||
<path d="M12 22V7" />
|
||||
<path d="M12 7H7.5a2.5 2.5 0 1 1 2.2-3.7L12 7Z" />
|
||||
<path d="M12 7h4.5a2.5 2.5 0 1 0-2.2-3.7L12 7Z" />
|
||||
</svg>
|
||||
</button>
|
||||
<div class="custom-select-menu" id="propsTypeMenu" role="listbox" aria-labelledby="propsTypeLabelText" hidden>
|
||||
<button type="button" role="option" data-value="RIDE" data-i18n="prop_type_ride">Ride</button>
|
||||
<button type="button" role="option" data-value="NOBLE_VIP" data-i18n="prop_type_noble_vip">Noble VIP</button>
|
||||
<button type="button" role="option" data-value="AVATAR_FRAME" data-i18n="prop_type_avatar_frame">Avatar Frame</button>
|
||||
<button type="button" role="option" data-value="CHAT_BUBBLE" data-i18n="prop_type_chat_bubble">Chat Bubble</button>
|
||||
<button type="button" role="option" data-value="DATA_CARD" data-i18n="prop_type_data_card">Profile Card</button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="props-status" id="propsStatus" role="status" hidden></div>
|
||||
<div class="props-list" id="propsList"></div>
|
||||
<button class="primary-action" id="sendPropsButton" type="button" disabled data-i18n="send">Send</button>
|
||||
</section>
|
||||
|
||||
<section class="card ban-card" id="banCard" hidden>
|
||||
<div class="section-head">
|
||||
<h2 data-i18n="ban_user">Ban User</h2>
|
||||
<span class="danger-chip" id="banEligibility">-</span>
|
||||
</div>
|
||||
<textarea id="banReason" maxlength="200" rows="3" placeholder="Ban reason" data-i18n-placeholder="ban_reason"></textarea>
|
||||
<button class="danger-action" id="banButton" type="button" disabled data-i18n="ban">Ban</button>
|
||||
<div class="form-status" id="banStatus" role="status" hidden></div>
|
||||
</span>
|
||||
<span class="action-item-copy">
|
||||
<span class="action-item-title" data-i18n="gift_props">Gift Props</span>
|
||||
</span>
|
||||
<svg class="action-item-arrow" viewBox="0 0 24 24" aria-hidden="true">
|
||||
<path d="m9 6 6 6-6 6" />
|
||||
</svg>
|
||||
</button>
|
||||
<button class="action-item is-danger" id="banEntryButton" type="button" disabled>
|
||||
<span class="action-item-icon" aria-hidden="true">
|
||||
<svg viewBox="0 0 24 24">
|
||||
<circle cx="12" cy="12" r="9" />
|
||||
<path d="m8 8 8 8" />
|
||||
</svg>
|
||||
</span>
|
||||
<span class="action-item-copy">
|
||||
<span class="action-item-title" data-i18n="ban_user">Ban User</span>
|
||||
</span>
|
||||
<svg class="action-item-arrow" viewBox="0 0 24 24" aria-hidden="true">
|
||||
<path d="m9 6 6 6-6 6" />
|
||||
</svg>
|
||||
</button>
|
||||
<button class="action-item" id="unbanEntryButton" type="button" disabled>
|
||||
<span class="action-item-icon" aria-hidden="true">
|
||||
<svg viewBox="0 0 24 24">
|
||||
<path d="M12 3 20 7v5c0 5-3.4 8-8 9-4.6-1-8-4-8-9V7l8-4Z" />
|
||||
<path d="m8.5 12.5 2.2 2.2 4.8-5" />
|
||||
</svg>
|
||||
</span>
|
||||
<span class="action-item-copy">
|
||||
<span class="action-item-title" data-i18n="unban_user">Unban User</span>
|
||||
</span>
|
||||
<svg class="action-item-arrow" viewBox="0 0 24 24" aria-hidden="true">
|
||||
<path d="m9 6 6 6-6 6" />
|
||||
</svg>
|
||||
</button>
|
||||
</section>
|
||||
</main>
|
||||
|
||||
<div class="modal-mask" id="giftModal" role="dialog" aria-modal="true" aria-labelledby="giftModalTitle" hidden>
|
||||
<section class="modal-sheet">
|
||||
<div class="modal-head">
|
||||
<h2 id="giftModalTitle" data-i18n="gift_props">Gift Props</h2>
|
||||
<button class="modal-close" type="button" data-modal-close aria-label="Close" data-i18n-aria="close">
|
||||
<svg viewBox="0 0 24 24" aria-hidden="true">
|
||||
<path d="M6 6 18 18M18 6 6 18" />
|
||||
</svg>
|
||||
</button>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<label class="field-label" id="propsTypeLabelText" data-i18n="gift_type">Gift Type</label>
|
||||
<div class="custom-select" id="propsTypeSelect" data-value="RIDE">
|
||||
<button
|
||||
class="custom-select-button"
|
||||
id="propsTypeButton"
|
||||
type="button"
|
||||
aria-expanded="false"
|
||||
aria-haspopup="listbox"
|
||||
aria-labelledby="propsTypeLabelText propsTypeSelectedLabel"
|
||||
>
|
||||
<span id="propsTypeSelectedLabel">Ride</span>
|
||||
<svg viewBox="0 0 24 24" aria-hidden="true">
|
||||
<path d="m7 9 5 5 5-5" />
|
||||
</svg>
|
||||
</button>
|
||||
<div class="custom-select-menu" id="propsTypeMenu" role="listbox" aria-labelledby="propsTypeLabelText" hidden>
|
||||
<button type="button" role="option" data-value="RIDE" data-i18n="prop_type_ride">Ride</button>
|
||||
<button type="button" role="option" data-value="NOBLE_VIP" data-i18n="prop_type_noble_vip">Noble VIP</button>
|
||||
<button type="button" role="option" data-value="AVATAR_FRAME" data-i18n="prop_type_avatar_frame">Avatar Frame</button>
|
||||
<button type="button" role="option" data-value="CHAT_BUBBLE" data-i18n="prop_type_chat_bubble">Chat Bubble</button>
|
||||
<button type="button" role="option" data-value="DATA_CARD" data-i18n="prop_type_data_card">Profile Card</button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="props-status" id="propsStatus" role="status" hidden></div>
|
||||
<div class="props-list" id="propsList"></div>
|
||||
<button class="primary-action" id="sendPropsButton" type="button" disabled data-i18n="send">Send</button>
|
||||
</div>
|
||||
</section>
|
||||
</div>
|
||||
|
||||
<div class="modal-mask" id="banModal" role="dialog" aria-modal="true" aria-labelledby="banModalTitle" hidden>
|
||||
<section class="modal-sheet">
|
||||
<div class="modal-head">
|
||||
<h2 id="banModalTitle" data-i18n="ban_user">Ban User</h2>
|
||||
<button class="modal-close" type="button" data-modal-close aria-label="Close" data-i18n-aria="close">
|
||||
<svg viewBox="0 0 24 24" aria-hidden="true">
|
||||
<path d="M6 6 18 18M18 6 6 18" />
|
||||
</svg>
|
||||
</button>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<span class="danger-chip" id="banEligibility">-</span>
|
||||
<textarea id="banReason" maxlength="200" rows="3" placeholder="Ban reason" data-i18n-placeholder="ban_reason"></textarea>
|
||||
<button class="danger-action" id="banButton" type="button" disabled data-i18n="ban">Ban</button>
|
||||
<div class="form-status" id="banStatus" role="status" hidden></div>
|
||||
</div>
|
||||
</section>
|
||||
</div>
|
||||
|
||||
<div class="modal-mask" id="unbanModal" role="dialog" aria-modal="true" aria-labelledby="unbanModalTitle" hidden>
|
||||
<section class="modal-sheet">
|
||||
<div class="modal-head">
|
||||
<h2 id="unbanModalTitle" data-i18n="unban_user">Unban User</h2>
|
||||
<button class="modal-close" type="button" data-modal-close aria-label="Close" data-i18n-aria="close">
|
||||
<svg viewBox="0 0 24 24" aria-hidden="true">
|
||||
<path d="M6 6 18 18M18 6 6 18" />
|
||||
</svg>
|
||||
</button>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<span class="danger-chip" id="unbanEligibility">-</span>
|
||||
<textarea id="unbanReason" maxlength="200" rows="3" placeholder="Unban reason" data-i18n-placeholder="unban_reason"></textarea>
|
||||
<button class="primary-action" id="unbanButton" type="button" disabled data-i18n="unban">Unban</button>
|
||||
<div class="form-status" id="unbanStatus" role="status" hidden></div>
|
||||
</div>
|
||||
</section>
|
||||
</div>
|
||||
|
||||
<div class="loading-mask" id="loadingMask" role="status" aria-live="polite">
|
||||
<div class="loader" aria-hidden="true"></div>
|
||||
<span data-i18n="loading">Loading...</span>
|
||||
</div>
|
||||
<div class="toast" id="toast" role="status" hidden></div>
|
||||
</div>
|
||||
<script src="./script.js?v=20260511-0108" defer></script>
|
||||
<script src="./script.js?v=20260511-0112" defer></script>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
@ -4,6 +4,7 @@
|
||||
"back": "رجوع",
|
||||
"title": "مركز المدير",
|
||||
"language_button_aria": "تغيير اللغة",
|
||||
"close": "إغلاق",
|
||||
"current_manager": "المدير الحالي",
|
||||
"user": "المستخدم",
|
||||
"user_search_placeholder": "أدخل معرّف المستخدم أو الحساب",
|
||||
@ -20,14 +21,18 @@
|
||||
"no_giftable_props": "لا توجد عناصر قابلة للإهداء",
|
||||
"send": "إرسال",
|
||||
"sending": "جار الإرسال...",
|
||||
"confirm_send": "هل تريد إرسال هذا العنصر؟",
|
||||
"send_success": "تم الإرسال بنجاح",
|
||||
"ban_user": "حظر المستخدم",
|
||||
"ban_reason": "سبب الحظر",
|
||||
"ban": "حظر",
|
||||
"confirm_ban": "هل تريد حظر هذا المستخدم؟",
|
||||
"submitting": "جار الإرسال...",
|
||||
"ban_success": "تم حظر المستخدم",
|
||||
"unban_user": "إلغاء حظر المستخدم",
|
||||
"unban_reason": "سبب إلغاء الحظر",
|
||||
"unban": "إلغاء الحظر",
|
||||
"unban_success": "تم إلغاء حظر المستخدم",
|
||||
"can_unban": "يمكن إلغاء الحظر",
|
||||
"cannot_unban": "لا يمكن إلغاء الحظر",
|
||||
"loading": "جار التحميل...",
|
||||
"uid_label": "UID",
|
||||
"days": "{count} يوم",
|
||||
@ -40,6 +45,8 @@
|
||||
"not_manager": "الحساب الحالي ليس مديرًا",
|
||||
"user_not_found": "المستخدم غير موجود",
|
||||
"user_recharged": "لدى هذا المستخدم سجلات شحن ولا يمكن حظره",
|
||||
"user_already_banned": "هذا المستخدم محظور بالفعل",
|
||||
"user_not_banned": "هذا المستخدم غير محظور",
|
||||
"prop_not_giftable": "هذا العنصر غير متاح كهديّة من المدير",
|
||||
"vip_not_giftable": "لا يمكن إهداء عنصر VIP هذا",
|
||||
"request_failed": "فشل الطلب",
|
||||
|
||||
@ -4,6 +4,7 @@
|
||||
"back": "Back",
|
||||
"title": "Manager Center",
|
||||
"language_button_aria": "Change language",
|
||||
"close": "Close",
|
||||
"current_manager": "Current Manager",
|
||||
"user": "User",
|
||||
"user_search_placeholder": "Enter user ID or account",
|
||||
@ -20,14 +21,18 @@
|
||||
"no_giftable_props": "No giftable props",
|
||||
"send": "Send",
|
||||
"sending": "Sending...",
|
||||
"confirm_send": "Send this prop?",
|
||||
"send_success": "Sent successfully",
|
||||
"ban_user": "Ban User",
|
||||
"ban_reason": "Ban reason",
|
||||
"ban": "Ban",
|
||||
"confirm_ban": "Ban this user?",
|
||||
"submitting": "Submitting...",
|
||||
"ban_success": "User banned",
|
||||
"unban_user": "Unban User",
|
||||
"unban_reason": "Unban reason",
|
||||
"unban": "Unban",
|
||||
"unban_success": "User unbanned",
|
||||
"can_unban": "Can unban",
|
||||
"cannot_unban": "Cannot unban",
|
||||
"loading": "Loading...",
|
||||
"uid_label": "UID",
|
||||
"days": "{count} days",
|
||||
@ -40,6 +45,8 @@
|
||||
"not_manager": "Current account is not a manager",
|
||||
"user_not_found": "User not found",
|
||||
"user_recharged": "This user has recharge records and cannot be banned",
|
||||
"user_already_banned": "This user is already banned",
|
||||
"user_not_banned": "This user is not banned",
|
||||
"prop_not_giftable": "This prop is not available for manager gifting",
|
||||
"vip_not_giftable": "This noble prop cannot be gifted",
|
||||
"request_failed": "Request failed",
|
||||
|
||||
@ -4,6 +4,7 @@
|
||||
"back": "Kembali",
|
||||
"title": "Pusat Manajer",
|
||||
"language_button_aria": "Ubah bahasa",
|
||||
"close": "Tutup",
|
||||
"current_manager": "Manajer Saat Ini",
|
||||
"user": "Pengguna",
|
||||
"user_search_placeholder": "Masukkan ID pengguna atau akun",
|
||||
@ -20,14 +21,18 @@
|
||||
"no_giftable_props": "Tidak ada properti yang dapat dikirim",
|
||||
"send": "Kirim",
|
||||
"sending": "Mengirim...",
|
||||
"confirm_send": "Kirim properti ini?",
|
||||
"send_success": "Berhasil dikirim",
|
||||
"ban_user": "Blokir Pengguna",
|
||||
"ban_reason": "Alasan blokir",
|
||||
"ban": "Blokir",
|
||||
"confirm_ban": "Blokir pengguna ini?",
|
||||
"submitting": "Mengirim...",
|
||||
"ban_success": "Pengguna diblokir",
|
||||
"unban_user": "Buka Blokir Pengguna",
|
||||
"unban_reason": "Alasan buka blokir",
|
||||
"unban": "Buka blokir",
|
||||
"unban_success": "Blokir pengguna dibuka",
|
||||
"can_unban": "Dapat dibuka",
|
||||
"cannot_unban": "Tidak dapat dibuka",
|
||||
"loading": "Memuat...",
|
||||
"uid_label": "UID",
|
||||
"days": "{count} hari",
|
||||
@ -40,6 +45,8 @@
|
||||
"not_manager": "Akun saat ini bukan manajer",
|
||||
"user_not_found": "Pengguna tidak ditemukan",
|
||||
"user_recharged": "Pengguna ini memiliki riwayat isi ulang dan tidak dapat diblokir",
|
||||
"user_already_banned": "Pengguna ini sudah diblokir",
|
||||
"user_not_banned": "Pengguna ini tidak diblokir",
|
||||
"prop_not_giftable": "Properti ini tidak tersedia untuk hadiah manajer",
|
||||
"vip_not_giftable": "Properti noble ini tidak dapat dikirim",
|
||||
"request_failed": "Permintaan gagal",
|
||||
|
||||
@ -4,6 +4,7 @@
|
||||
"back": "Geri",
|
||||
"title": "Yönetici Merkezi",
|
||||
"language_button_aria": "Dili değiştir",
|
||||
"close": "Kapat",
|
||||
"current_manager": "Mevcut Yönetici",
|
||||
"user": "Kullanıcı",
|
||||
"user_search_placeholder": "Kullanıcı ID veya hesap gir",
|
||||
@ -20,14 +21,18 @@
|
||||
"no_giftable_props": "Gönderilebilir eşya yok",
|
||||
"send": "Gönder",
|
||||
"sending": "Gönderiliyor...",
|
||||
"confirm_send": "Bu eşyayı göndermek istiyor musun?",
|
||||
"send_success": "Başarıyla gönderildi",
|
||||
"ban_user": "Kullanıcıyı Yasakla",
|
||||
"ban_reason": "Yasaklama nedeni",
|
||||
"ban": "Yasakla",
|
||||
"confirm_ban": "Bu kullanıcıyı yasaklamak istiyor musun?",
|
||||
"submitting": "Gönderiliyor...",
|
||||
"ban_success": "Kullanıcı yasaklandı",
|
||||
"unban_user": "Yasağı Kaldır",
|
||||
"unban_reason": "Yasağı kaldırma nedeni",
|
||||
"unban": "Yasağı kaldır",
|
||||
"unban_success": "Kullanıcının yasağı kaldırıldı",
|
||||
"can_unban": "Yasak kaldırılabilir",
|
||||
"cannot_unban": "Yasak kaldırılamaz",
|
||||
"loading": "Yükleniyor...",
|
||||
"uid_label": "UID",
|
||||
"days": "{count} gün",
|
||||
@ -40,6 +45,8 @@
|
||||
"not_manager": "Mevcut hesap yönetici değil",
|
||||
"user_not_found": "Kullanıcı bulunamadı",
|
||||
"user_recharged": "Bu kullanıcının yükleme kaydı var, yasaklanamaz",
|
||||
"user_already_banned": "Bu kullanıcı zaten yasaklı",
|
||||
"user_not_banned": "Bu kullanıcı yasaklı değil",
|
||||
"prop_not_giftable": "Bu eşya yönetici hediyesi için açık değil",
|
||||
"vip_not_giftable": "Bu noble eşyası gönderilemez",
|
||||
"request_failed": "İstek başarısız",
|
||||
|
||||
@ -18,6 +18,7 @@
|
||||
back: "Back",
|
||||
title: "Manager Center",
|
||||
language_button_aria: "Change language",
|
||||
close: "Close",
|
||||
current_manager: "Current Manager",
|
||||
user: "User",
|
||||
user_search_placeholder: "Enter user ID or account",
|
||||
@ -34,14 +35,18 @@
|
||||
no_giftable_props: "No giftable props",
|
||||
send: "Send",
|
||||
sending: "Sending...",
|
||||
confirm_send: "Send this prop?",
|
||||
send_success: "Sent successfully",
|
||||
ban_user: "Ban User",
|
||||
ban_reason: "Ban reason",
|
||||
ban: "Ban",
|
||||
confirm_ban: "Ban this user?",
|
||||
submitting: "Submitting...",
|
||||
ban_success: "User banned",
|
||||
unban_user: "Unban User",
|
||||
unban_reason: "Unban reason",
|
||||
unban: "Unban",
|
||||
unban_success: "User unbanned",
|
||||
can_unban: "Can unban",
|
||||
cannot_unban: "Cannot unban",
|
||||
loading: "Loading...",
|
||||
uid_label: "UID",
|
||||
days: "{count} days",
|
||||
@ -54,6 +59,8 @@
|
||||
not_manager: "Current account is not a manager",
|
||||
user_not_found: "User not found",
|
||||
user_recharged: "This user has recharge records and cannot be banned",
|
||||
user_already_banned: "This user is already banned",
|
||||
user_not_banned: "This user is not banned",
|
||||
prop_not_giftable: "This prop is not available for manager gifting",
|
||||
vip_not_giftable: "This noble prop cannot be gifted",
|
||||
request_failed: "Request failed",
|
||||
@ -65,6 +72,7 @@
|
||||
back: "رجوع",
|
||||
title: "مركز المدير",
|
||||
language_button_aria: "تغيير اللغة",
|
||||
close: "إغلاق",
|
||||
current_manager: "المدير الحالي",
|
||||
user: "المستخدم",
|
||||
user_search_placeholder: "أدخل معرّف المستخدم أو الحساب",
|
||||
@ -81,14 +89,18 @@
|
||||
no_giftable_props: "لا توجد عناصر قابلة للإهداء",
|
||||
send: "إرسال",
|
||||
sending: "جار الإرسال...",
|
||||
confirm_send: "هل تريد إرسال هذا العنصر؟",
|
||||
send_success: "تم الإرسال بنجاح",
|
||||
ban_user: "حظر المستخدم",
|
||||
ban_reason: "سبب الحظر",
|
||||
ban: "حظر",
|
||||
confirm_ban: "هل تريد حظر هذا المستخدم؟",
|
||||
submitting: "جار الإرسال...",
|
||||
ban_success: "تم حظر المستخدم",
|
||||
unban_user: "إلغاء حظر المستخدم",
|
||||
unban_reason: "سبب إلغاء الحظر",
|
||||
unban: "إلغاء الحظر",
|
||||
unban_success: "تم إلغاء حظر المستخدم",
|
||||
can_unban: "يمكن إلغاء الحظر",
|
||||
cannot_unban: "لا يمكن إلغاء الحظر",
|
||||
loading: "جار التحميل...",
|
||||
uid_label: "UID",
|
||||
days: "{count} يوم",
|
||||
@ -101,6 +113,8 @@
|
||||
not_manager: "الحساب الحالي ليس مديرًا",
|
||||
user_not_found: "المستخدم غير موجود",
|
||||
user_recharged: "لدى هذا المستخدم سجلات شحن ولا يمكن حظره",
|
||||
user_already_banned: "هذا المستخدم محظور بالفعل",
|
||||
user_not_banned: "هذا المستخدم غير محظور",
|
||||
prop_not_giftable: "هذا العنصر غير متاح كهديّة من المدير",
|
||||
vip_not_giftable: "لا يمكن إهداء عنصر VIP هذا",
|
||||
request_failed: "فشل الطلب",
|
||||
@ -112,6 +126,7 @@
|
||||
back: "Geri",
|
||||
title: "Yönetici Merkezi",
|
||||
language_button_aria: "Dili değiştir",
|
||||
close: "Kapat",
|
||||
current_manager: "Mevcut Yönetici",
|
||||
user: "Kullanıcı",
|
||||
user_search_placeholder: "Kullanıcı ID veya hesap gir",
|
||||
@ -128,14 +143,18 @@
|
||||
no_giftable_props: "Gönderilebilir eşya yok",
|
||||
send: "Gönder",
|
||||
sending: "Gönderiliyor...",
|
||||
confirm_send: "Bu eşyayı göndermek istiyor musun?",
|
||||
send_success: "Başarıyla gönderildi",
|
||||
ban_user: "Kullanıcıyı Yasakla",
|
||||
ban_reason: "Yasaklama nedeni",
|
||||
ban: "Yasakla",
|
||||
confirm_ban: "Bu kullanıcıyı yasaklamak istiyor musun?",
|
||||
submitting: "Gönderiliyor...",
|
||||
ban_success: "Kullanıcı yasaklandı",
|
||||
unban_user: "Yasağı Kaldır",
|
||||
unban_reason: "Yasağı kaldırma nedeni",
|
||||
unban: "Yasağı kaldır",
|
||||
unban_success: "Kullanıcının yasağı kaldırıldı",
|
||||
can_unban: "Yasak kaldırılabilir",
|
||||
cannot_unban: "Yasak kaldırılamaz",
|
||||
loading: "Yükleniyor...",
|
||||
uid_label: "UID",
|
||||
days: "{count} gün",
|
||||
@ -148,6 +167,8 @@
|
||||
not_manager: "Mevcut hesap yönetici değil",
|
||||
user_not_found: "Kullanıcı bulunamadı",
|
||||
user_recharged: "Bu kullanıcının yükleme kaydı var, yasaklanamaz",
|
||||
user_already_banned: "Bu kullanıcı zaten yasaklı",
|
||||
user_not_banned: "Bu kullanıcı yasaklı değil",
|
||||
prop_not_giftable: "Bu eşya yönetici hediyesi için açık değil",
|
||||
vip_not_giftable: "Bu noble eşyası gönderilemez",
|
||||
request_failed: "İstek başarısız",
|
||||
@ -159,6 +180,7 @@
|
||||
back: "Kembali",
|
||||
title: "Pusat Manajer",
|
||||
language_button_aria: "Ubah bahasa",
|
||||
close: "Tutup",
|
||||
current_manager: "Manajer Saat Ini",
|
||||
user: "Pengguna",
|
||||
user_search_placeholder: "Masukkan ID pengguna atau akun",
|
||||
@ -175,14 +197,18 @@
|
||||
no_giftable_props: "Tidak ada properti yang dapat dikirim",
|
||||
send: "Kirim",
|
||||
sending: "Mengirim...",
|
||||
confirm_send: "Kirim properti ini?",
|
||||
send_success: "Berhasil dikirim",
|
||||
ban_user: "Blokir Pengguna",
|
||||
ban_reason: "Alasan blokir",
|
||||
ban: "Blokir",
|
||||
confirm_ban: "Blokir pengguna ini?",
|
||||
submitting: "Mengirim...",
|
||||
ban_success: "Pengguna diblokir",
|
||||
unban_user: "Buka Blokir Pengguna",
|
||||
unban_reason: "Alasan buka blokir",
|
||||
unban: "Buka blokir",
|
||||
unban_success: "Blokir pengguna dibuka",
|
||||
can_unban: "Dapat dibuka",
|
||||
cannot_unban: "Tidak dapat dibuka",
|
||||
loading: "Memuat...",
|
||||
uid_label: "UID",
|
||||
days: "{count} hari",
|
||||
@ -195,6 +221,8 @@
|
||||
not_manager: "Akun saat ini bukan manajer",
|
||||
user_not_found: "Pengguna tidak ditemukan",
|
||||
user_recharged: "Pengguna ini memiliki riwayat isi ulang dan tidak dapat diblokir",
|
||||
user_already_banned: "Pengguna ini sudah diblokir",
|
||||
user_not_banned: "Pengguna ini tidak diblokir",
|
||||
prop_not_giftable: "Properti ini tidak tersedia untuk hadiah manajer",
|
||||
vip_not_giftable: "Properti noble ini tidak dapat dikirim",
|
||||
request_failed: "Permintaan gagal",
|
||||
@ -261,7 +289,7 @@
|
||||
if (window.location.protocol === "file:") return fallbackMessages[normalizedLang];
|
||||
|
||||
try {
|
||||
const response = await fetch(`./locales/${normalizedLang}.json?v=20260511-0105`, { cache: "no-store" });
|
||||
const response = await fetch(`./locales/${normalizedLang}.json?v=20260511-0107`, { cache: "no-store" });
|
||||
if (response.ok) return await response.json();
|
||||
} catch (error) {
|
||||
return fallbackMessages[normalizedLang];
|
||||
@ -477,6 +505,10 @@
|
||||
return "/app/h5/manager-center/users/ban";
|
||||
}
|
||||
|
||||
function endpointUnbanUser() {
|
||||
return "/app/h5/manager-center/users/unban";
|
||||
}
|
||||
|
||||
function setLoading(isLoading) {
|
||||
const root = $(".manager-center");
|
||||
const mask = $("#loadingMask");
|
||||
@ -502,6 +534,58 @@
|
||||
}, 2300);
|
||||
}
|
||||
|
||||
function syncModalState() {
|
||||
document.body.classList.toggle("is-modal-open", Boolean(document.querySelector(".modal-mask:not([hidden])")));
|
||||
}
|
||||
|
||||
function setModalOpen(selector, open) {
|
||||
const modal = $(selector);
|
||||
if (!modal) return;
|
||||
modal.hidden = !open;
|
||||
if (open) {
|
||||
setLanguageMenuOpen(false);
|
||||
setPropsTypeMenuOpen(false);
|
||||
}
|
||||
syncModalState();
|
||||
}
|
||||
|
||||
function closeModals() {
|
||||
document.querySelectorAll(".modal-mask").forEach((modal) => {
|
||||
modal.hidden = true;
|
||||
});
|
||||
setPropsTypeMenuOpen(false);
|
||||
syncModalState();
|
||||
}
|
||||
|
||||
function openGiftModal() {
|
||||
if (!state.target) {
|
||||
showToast(message("enter_user"));
|
||||
return;
|
||||
}
|
||||
setModalOpen("#giftModal", true);
|
||||
updateActionState();
|
||||
}
|
||||
|
||||
function openBanModal() {
|
||||
if (!state.target) {
|
||||
showToast(message("enter_user"));
|
||||
return;
|
||||
}
|
||||
setStatus($("#banStatus"), "");
|
||||
setModalOpen("#banModal", true);
|
||||
updateActionState();
|
||||
}
|
||||
|
||||
function openUnbanModal() {
|
||||
if (!state.target) {
|
||||
showToast(message("enter_user"));
|
||||
return;
|
||||
}
|
||||
setStatus($("#unbanStatus"), "");
|
||||
setModalOpen("#unbanModal", true);
|
||||
updateActionState();
|
||||
}
|
||||
|
||||
function closePage() {
|
||||
try {
|
||||
if (window.app && typeof window.app.closePage === "function") {
|
||||
@ -554,7 +638,12 @@
|
||||
}
|
||||
|
||||
function canBanTarget(target) {
|
||||
return Boolean(target) && target.canBan !== false && !target.hasRecharge;
|
||||
return Boolean(target) && target.canBan !== false && !target.hasRecharge && !canUnbanTarget(target);
|
||||
}
|
||||
|
||||
function canUnbanTarget(target) {
|
||||
const status = String(target?.accountStatus || "").trim().toUpperCase();
|
||||
return Boolean(target) && (status === "FREEZE" || status === "ARCHIVE" || status === "ARCHIVE_DEVICE");
|
||||
}
|
||||
|
||||
function userIDText(user) {
|
||||
@ -578,24 +667,33 @@
|
||||
|
||||
function renderTarget() {
|
||||
const card = $("#targetCard");
|
||||
const banCard = $("#banCard");
|
||||
const actionCard = $("#actionCard");
|
||||
if (!state.target) {
|
||||
if (card) card.hidden = true;
|
||||
if (banCard) banCard.hidden = true;
|
||||
if (actionCard) actionCard.hidden = true;
|
||||
closeModals();
|
||||
updateActionState();
|
||||
return;
|
||||
}
|
||||
|
||||
const target = state.target;
|
||||
card.hidden = false;
|
||||
banCard.hidden = false;
|
||||
if (card) card.hidden = false;
|
||||
if (actionCard) actionCard.hidden = false;
|
||||
$("#targetName").textContent = displayName(target);
|
||||
$("#targetUid").textContent = userIDText(target);
|
||||
$("#targetAccountStatus").textContent = target.accountStatus || "-";
|
||||
const canBan = canBanTarget(target);
|
||||
const banEligibility = $("#banEligibility");
|
||||
banEligibility.textContent = canBan ? message("can_ban") : message("cannot_ban");
|
||||
banEligibility.classList.toggle("is-danger", !canBan);
|
||||
if (banEligibility) {
|
||||
banEligibility.textContent = canBan ? message("can_ban") : message("cannot_ban");
|
||||
banEligibility.classList.toggle("is-danger", !canBan);
|
||||
}
|
||||
const canUnban = canUnbanTarget(target);
|
||||
const unbanEligibility = $("#unbanEligibility");
|
||||
if (unbanEligibility) {
|
||||
unbanEligibility.textContent = canUnban ? message("can_unban") : message("cannot_unban");
|
||||
unbanEligibility.classList.toggle("is-danger", !canUnban);
|
||||
}
|
||||
renderAvatar("#targetAvatar", "#targetAvatarFallback", target.userAvatar, displayName(target), "U");
|
||||
updateActionState();
|
||||
}
|
||||
@ -659,10 +757,18 @@
|
||||
}
|
||||
|
||||
function updateActionState() {
|
||||
const giftEntryButton = $("#giftEntryButton");
|
||||
const banEntryButton = $("#banEntryButton");
|
||||
const unbanEntryButton = $("#unbanEntryButton");
|
||||
const sendButton = $("#sendPropsButton");
|
||||
const banButton = $("#banButton");
|
||||
const unbanButton = $("#unbanButton");
|
||||
if (giftEntryButton) giftEntryButton.disabled = !state.target;
|
||||
if (banEntryButton) banEntryButton.disabled = !state.target;
|
||||
if (unbanEntryButton) unbanEntryButton.disabled = !state.target;
|
||||
if (sendButton) sendButton.disabled = !state.target || !state.selectedPropsId;
|
||||
if (banButton) banButton.disabled = !canBanTarget(state.target);
|
||||
if (unbanButton) unbanButton.disabled = !canUnbanTarget(state.target);
|
||||
}
|
||||
|
||||
async function loadProfile() {
|
||||
@ -710,7 +816,6 @@
|
||||
|
||||
async function sendProps() {
|
||||
if (!state.target || !state.selectedPropsId) return;
|
||||
if (!window.confirm(message("confirm_send"))) return;
|
||||
|
||||
const button = $("#sendPropsButton");
|
||||
button.disabled = true;
|
||||
@ -722,6 +827,7 @@
|
||||
propsId: state.selectedPropsId
|
||||
}
|
||||
});
|
||||
setModalOpen("#giftModal", false);
|
||||
showToast(message("send_success"));
|
||||
} catch (error) {
|
||||
showToast(friendlyError(error));
|
||||
@ -732,7 +838,6 @@
|
||||
|
||||
async function banUser() {
|
||||
if (!canBanTarget(state.target)) return;
|
||||
if (!window.confirm(message("confirm_ban"))) return;
|
||||
|
||||
const button = $("#banButton");
|
||||
button.disabled = true;
|
||||
@ -747,6 +852,7 @@
|
||||
});
|
||||
state.target.accountStatus = "ARCHIVE";
|
||||
renderTarget();
|
||||
setModalOpen("#banModal", false);
|
||||
setStatus($("#banStatus"), "");
|
||||
showToast(message("ban_success"));
|
||||
} catch (error) {
|
||||
@ -756,12 +862,40 @@
|
||||
}
|
||||
}
|
||||
|
||||
async function unbanUser() {
|
||||
if (!canUnbanTarget(state.target)) return;
|
||||
|
||||
const button = $("#unbanButton");
|
||||
button.disabled = true;
|
||||
setStatus($("#unbanStatus"), message("submitting"));
|
||||
try {
|
||||
await requestGoJSON(endpointUnbanUser(), {
|
||||
method: "POST",
|
||||
body: {
|
||||
userId: displayUserID(state.target),
|
||||
reason: $("#unbanReason").value || ""
|
||||
}
|
||||
});
|
||||
state.target.accountStatus = "NORMAL";
|
||||
renderTarget();
|
||||
setModalOpen("#unbanModal", false);
|
||||
setStatus($("#unbanStatus"), "");
|
||||
showToast(message("unban_success"));
|
||||
} catch (error) {
|
||||
setStatus($("#unbanStatus"), friendlyError(error), "error");
|
||||
} finally {
|
||||
updateActionState();
|
||||
}
|
||||
}
|
||||
|
||||
function friendlyError(error) {
|
||||
const code = error?.code || error?.response?.code || error?.response?.errorCodeName || "";
|
||||
if (code === "missing_token") return message("missing_token");
|
||||
if (code === "not_manager") return message("not_manager");
|
||||
if (code === "user_not_found") return message("user_not_found");
|
||||
if (code === "user_recharged") return message("user_recharged");
|
||||
if (code === "user_already_banned") return message("user_already_banned");
|
||||
if (code === "user_not_banned") return message("user_not_banned");
|
||||
if (code === "prop_not_giftable") return message("prop_not_giftable");
|
||||
if (code === "vip_not_giftable") return message("vip_not_giftable");
|
||||
return error?.message || message("request_failed");
|
||||
@ -784,6 +918,17 @@
|
||||
setLanguageMenuOpen(false);
|
||||
setPropsTypeMenuOpen(false);
|
||||
});
|
||||
$("#giftEntryButton")?.addEventListener("click", openGiftModal);
|
||||
$("#banEntryButton")?.addEventListener("click", openBanModal);
|
||||
$("#unbanEntryButton")?.addEventListener("click", openUnbanModal);
|
||||
document.querySelectorAll("[data-modal-close]").forEach((button) => {
|
||||
button.addEventListener("click", closeModals);
|
||||
});
|
||||
document.querySelectorAll(".modal-mask").forEach((modal) => {
|
||||
modal.addEventListener("click", (event) => {
|
||||
if (event.target === modal) closeModals();
|
||||
});
|
||||
});
|
||||
$("#propsTypeButton")?.addEventListener("click", (event) => {
|
||||
event.stopPropagation();
|
||||
setLanguageMenuOpen(false);
|
||||
@ -799,10 +944,12 @@
|
||||
if (event.key !== "Escape") return;
|
||||
setLanguageMenuOpen(false);
|
||||
setPropsTypeMenuOpen(false);
|
||||
closeModals();
|
||||
});
|
||||
$("#searchForm")?.addEventListener("submit", searchUser);
|
||||
$("#sendPropsButton")?.addEventListener("click", sendProps);
|
||||
$("#banButton")?.addEventListener("click", banUser);
|
||||
$("#unbanButton")?.addEventListener("click", unbanUser);
|
||||
}
|
||||
|
||||
async function init() {
|
||||
|
||||
@ -34,6 +34,10 @@ body {
|
||||
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;
|
||||
}
|
||||
|
||||
body.is-modal-open {
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
button,
|
||||
input,
|
||||
textarea {
|
||||
@ -268,12 +272,79 @@ button:disabled {
|
||||
color: var(--danger);
|
||||
}
|
||||
|
||||
.search-card,
|
||||
.gift-card,
|
||||
.ban-card {
|
||||
.search-card {
|
||||
padding: 14px;
|
||||
}
|
||||
|
||||
.action-card {
|
||||
display: grid;
|
||||
gap: 4px;
|
||||
padding: 6px;
|
||||
}
|
||||
|
||||
.action-item {
|
||||
display: grid;
|
||||
grid-template-columns: 42px minmax(0, 1fr) 24px;
|
||||
gap: 10px;
|
||||
align-items: center;
|
||||
width: 100%;
|
||||
min-height: 58px;
|
||||
border-radius: 6px;
|
||||
padding: 8px;
|
||||
background: #fff;
|
||||
color: var(--text);
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
.action-item:active {
|
||||
background: #f4f7f8;
|
||||
}
|
||||
|
||||
.action-item-icon {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
width: 42px;
|
||||
height: 42px;
|
||||
border-radius: 8px;
|
||||
background: #e7f8f4;
|
||||
color: var(--primary-dark);
|
||||
}
|
||||
|
||||
.action-item.is-danger .action-item-icon {
|
||||
background: var(--danger-bg);
|
||||
color: var(--danger);
|
||||
}
|
||||
|
||||
.action-item-icon svg,
|
||||
.action-item-arrow {
|
||||
width: 22px;
|
||||
height: 22px;
|
||||
fill: none;
|
||||
stroke: currentColor;
|
||||
stroke-linecap: round;
|
||||
stroke-linejoin: round;
|
||||
stroke-width: 2.2;
|
||||
}
|
||||
|
||||
.action-item-copy {
|
||||
display: grid;
|
||||
min-width: 0;
|
||||
}
|
||||
|
||||
.action-item-title {
|
||||
overflow: hidden;
|
||||
font-size: 15px;
|
||||
font-weight: 900;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.action-item-arrow {
|
||||
justify-self: end;
|
||||
color: #9aa4af;
|
||||
}
|
||||
|
||||
.section-head {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
@ -560,6 +631,84 @@ textarea:focus {
|
||||
color: var(--danger);
|
||||
}
|
||||
|
||||
.modal-mask {
|
||||
position: fixed;
|
||||
z-index: 30;
|
||||
inset: 0;
|
||||
display: flex;
|
||||
align-items: flex-end;
|
||||
justify-content: center;
|
||||
padding-top: 48px;
|
||||
background: rgba(17, 24, 32, 0.48);
|
||||
}
|
||||
|
||||
.modal-sheet {
|
||||
display: flex;
|
||||
width: min(100%, 430px);
|
||||
max-height: calc(100vh - 48px);
|
||||
flex-direction: column;
|
||||
overflow: hidden;
|
||||
border-radius: 8px 8px 0 0;
|
||||
background: var(--card-bg);
|
||||
box-shadow: 0 -18px 44px rgba(17, 24, 32, 0.22);
|
||||
}
|
||||
|
||||
.modal-head {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
gap: 12px;
|
||||
padding: 14px 14px 10px;
|
||||
border-bottom: 1px solid var(--line);
|
||||
}
|
||||
|
||||
.modal-head h2 {
|
||||
margin: 0;
|
||||
font-size: 17px;
|
||||
font-weight: 900;
|
||||
letter-spacing: 0;
|
||||
}
|
||||
|
||||
.modal-close {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
flex: 0 0 34px;
|
||||
width: 34px;
|
||||
height: 34px;
|
||||
border-radius: 50%;
|
||||
background: #f2f4f7;
|
||||
color: #48525f;
|
||||
}
|
||||
|
||||
.modal-close svg {
|
||||
width: 20px;
|
||||
height: 20px;
|
||||
fill: none;
|
||||
stroke: currentColor;
|
||||
stroke-linecap: round;
|
||||
stroke-width: 2.4;
|
||||
}
|
||||
|
||||
.modal-body {
|
||||
overflow-y: auto;
|
||||
padding: 14px 14px calc(18px + env(safe-area-inset-bottom));
|
||||
}
|
||||
|
||||
.modal-body .danger-chip {
|
||||
display: flex;
|
||||
width: fit-content;
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
|
||||
.modal-body textarea {
|
||||
display: block;
|
||||
}
|
||||
|
||||
.modal-body .props-list {
|
||||
max-height: min(42vh, 330px);
|
||||
}
|
||||
|
||||
.loading-mask {
|
||||
position: absolute;
|
||||
z-index: 20;
|
||||
@ -614,7 +763,8 @@ textarea:focus {
|
||||
[dir="rtl"] textarea,
|
||||
[dir="rtl"] .custom-select-button,
|
||||
[dir="rtl"] .custom-select-menu button,
|
||||
[dir="rtl"] .prop-option {
|
||||
[dir="rtl"] .prop-option,
|
||||
[dir="rtl"] .action-item {
|
||||
text-align: right;
|
||||
}
|
||||
|
||||
@ -622,6 +772,10 @@ textarea:focus {
|
||||
padding: 0 14px 0 12px;
|
||||
}
|
||||
|
||||
[dir="rtl"] .action-item-arrow {
|
||||
transform: rotate(180deg);
|
||||
}
|
||||
|
||||
@keyframes spin {
|
||||
to {
|
||||
transform: rotate(360deg);
|
||||
|
||||
@ -4,7 +4,7 @@
|
||||
<meta charset="UTF-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no, viewport-fit=cover" />
|
||||
<title>Recharge Center</title>
|
||||
<link rel="stylesheet" href="./style.css?v=20260430-0109" />
|
||||
<link rel="stylesheet" href="./style.css?v=20260511-0100" />
|
||||
</head>
|
||||
<body>
|
||||
<div class="recharge-center" aria-label="Recharge Center" data-i18n-aria="page_label" data-loading="true">
|
||||
@ -105,6 +105,39 @@
|
||||
<button class="mini-action mini-action-icon" type="button" data-change-target aria-label="Change" data-i18n-aria="change">X</button>
|
||||
</section>
|
||||
|
||||
<section class="card auto-verify-card" id="autoVerifyCard" hidden>
|
||||
<div class="section-head">
|
||||
<div>
|
||||
<div class="section-title" data-i18n="auto_verify_title">Auto recharge verification</div>
|
||||
<div class="section-subtitle" data-i18n="auto_verify_subtitle">Verify Binance transfer and issue coins</div>
|
||||
</div>
|
||||
<button class="auto-verify-toggle" id="autoVerifyToggle" type="button" data-i18n="open_auto_verify">Open</button>
|
||||
</div>
|
||||
<form class="auto-verify-form" id="autoVerifyForm" autocomplete="off" hidden>
|
||||
<label class="auto-field">
|
||||
<span data-i18n="order_no">Order no.</span>
|
||||
<input id="autoOrderInput" type="text" inputmode="text" data-i18n-placeholder="order_no_placeholder" placeholder="Enter order no." />
|
||||
</label>
|
||||
<label class="auto-field">
|
||||
<span data-i18n="transfer_amount_usdt">Transfer amount</span>
|
||||
<input id="autoAmountInput" type="text" inputmode="decimal" data-i18n-placeholder="transfer_amount_placeholder" placeholder="Enter USDT amount" />
|
||||
</label>
|
||||
<label class="auto-field">
|
||||
<span data-i18n="transfer_type">Transfer type</span>
|
||||
<select id="autoTransferType">
|
||||
<option value="BINANCE_PAY" data-i18n="binance_pay_transfer">Binance internal</option>
|
||||
<option value="CHAIN" data-i18n="chain_transfer">On-chain transfer</option>
|
||||
</select>
|
||||
</label>
|
||||
<label class="auto-field">
|
||||
<span data-i18n="bill_no">Bill no.</span>
|
||||
<input id="autoBillInput" type="text" inputmode="text" data-i18n-placeholder="bill_no_placeholder" placeholder="Enter bill no. or txId" />
|
||||
</label>
|
||||
<button id="autoVerifyButton" type="submit" data-i18n="verify_recharge">Verify recharge</button>
|
||||
</form>
|
||||
<div class="form-status" id="autoVerifyStatus" role="status" hidden></div>
|
||||
</section>
|
||||
|
||||
<section class="card coin-recharge-card" id="coinRechargeCard" hidden>
|
||||
<div class="section-head">
|
||||
<div>
|
||||
@ -205,6 +238,6 @@
|
||||
|
||||
<div class="toast" id="toast" role="status" aria-live="polite" hidden></div>
|
||||
</div>
|
||||
<script src="./script.js?v=20260430-0109" defer></script>
|
||||
<script src="./script.js?v=20260511-0100" defer></script>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
@ -44,6 +44,24 @@
|
||||
coin_recharge_subtitle: "Enter coins amount",
|
||||
coin_amount_placeholder: "Enter coins amount",
|
||||
confirm_recharge: "Confirm recharge",
|
||||
auto_verify_title: "Auto recharge verification",
|
||||
auto_verify_subtitle: "Verify Binance transfer and issue coins",
|
||||
open_auto_verify: "Open",
|
||||
close_auto_verify: "Close",
|
||||
order_no: "Order no.",
|
||||
order_no_placeholder: "Enter order no.",
|
||||
transfer_amount_usdt: "Transfer amount",
|
||||
transfer_amount_placeholder: "Enter USDT amount",
|
||||
transfer_type: "Transfer type",
|
||||
binance_pay_transfer: "Binance internal",
|
||||
chain_transfer: "On-chain transfer",
|
||||
bill_no: "Bill no.",
|
||||
bill_no_placeholder: "Enter bill no. or txId",
|
||||
verify_recharge: "Verify recharge",
|
||||
verifying: "Verifying...",
|
||||
auto_verify_success: "Verification success",
|
||||
please_enter_order_no: "Please enter order no.",
|
||||
please_enter_bill_no: "Please enter bill no.",
|
||||
loading_data: "Loading...",
|
||||
loading_mask: "loading....",
|
||||
no_country: "No supported country",
|
||||
@ -106,6 +124,24 @@
|
||||
coin_recharge_subtitle: "أدخل عدد العملات",
|
||||
coin_amount_placeholder: "أدخل عدد العملات",
|
||||
confirm_recharge: "تأكيد الشحن",
|
||||
auto_verify_title: "تحقق الشحن التلقائي",
|
||||
auto_verify_subtitle: "تحقق من تحويل Binance وأرسل العملات",
|
||||
open_auto_verify: "فتح",
|
||||
close_auto_verify: "إغلاق",
|
||||
order_no: "رقم الطلب",
|
||||
order_no_placeholder: "أدخل رقم الطلب",
|
||||
transfer_amount_usdt: "مبلغ التحويل",
|
||||
transfer_amount_placeholder: "أدخل مبلغ USDT",
|
||||
transfer_type: "نوع التحويل",
|
||||
binance_pay_transfer: "تحويل داخل Binance",
|
||||
chain_transfer: "تحويل على الشبكة",
|
||||
bill_no: "رقم الفاتورة",
|
||||
bill_no_placeholder: "أدخل رقم الفاتورة أو txId",
|
||||
verify_recharge: "تحقق من الشحن",
|
||||
verifying: "جار التحقق...",
|
||||
auto_verify_success: "تم التحقق بنجاح",
|
||||
please_enter_order_no: "يرجى إدخال رقم الطلب",
|
||||
please_enter_bill_no: "يرجى إدخال رقم الفاتورة",
|
||||
loading_data: "جار التحميل...",
|
||||
loading_mask: "جار التحميل....",
|
||||
no_country: "لا توجد دولة مدعومة",
|
||||
@ -168,6 +204,24 @@
|
||||
coin_recharge_subtitle: "Coin miktari gir",
|
||||
coin_amount_placeholder: "Coin miktari gir",
|
||||
confirm_recharge: "Yuklemeyi onayla",
|
||||
auto_verify_title: "Otomatik yukleme dogrulama",
|
||||
auto_verify_subtitle: "Binance transferini dogrula ve coin ver",
|
||||
open_auto_verify: "Ac",
|
||||
close_auto_verify: "Kapat",
|
||||
order_no: "Siparis no.",
|
||||
order_no_placeholder: "Siparis no. gir",
|
||||
transfer_amount_usdt: "Transfer tutari",
|
||||
transfer_amount_placeholder: "USDT tutari gir",
|
||||
transfer_type: "Transfer tipi",
|
||||
binance_pay_transfer: "Binance ici",
|
||||
chain_transfer: "Zincir uzeri",
|
||||
bill_no: "Fatura no.",
|
||||
bill_no_placeholder: "Fatura no. veya txId gir",
|
||||
verify_recharge: "Yuklemeyi dogrula",
|
||||
verifying: "Dogrulaniyor...",
|
||||
auto_verify_success: "Dogrulama basarili",
|
||||
please_enter_order_no: "Lutfen siparis no. girin",
|
||||
please_enter_bill_no: "Lutfen fatura no. girin",
|
||||
loading_data: "Yukleniyor...",
|
||||
loading_mask: "yukleniyor....",
|
||||
no_country: "Desteklenen ulke yok",
|
||||
@ -230,6 +284,24 @@
|
||||
coin_recharge_subtitle: "Masukkan jumlah koin",
|
||||
coin_amount_placeholder: "Masukkan jumlah koin",
|
||||
confirm_recharge: "Konfirmasi isi ulang",
|
||||
auto_verify_title: "Verifikasi isi ulang otomatis",
|
||||
auto_verify_subtitle: "Verifikasi transfer Binance dan kirim koin",
|
||||
open_auto_verify: "Buka",
|
||||
close_auto_verify: "Tutup",
|
||||
order_no: "No. pesanan",
|
||||
order_no_placeholder: "Masukkan no. pesanan",
|
||||
transfer_amount_usdt: "Jumlah transfer",
|
||||
transfer_amount_placeholder: "Masukkan jumlah USDT",
|
||||
transfer_type: "Jenis transfer",
|
||||
binance_pay_transfer: "Internal Binance",
|
||||
chain_transfer: "Transfer on-chain",
|
||||
bill_no: "No. tagihan",
|
||||
bill_no_placeholder: "Masukkan no. tagihan atau txId",
|
||||
verify_recharge: "Verifikasi isi ulang",
|
||||
verifying: "Memverifikasi...",
|
||||
auto_verify_success: "Verifikasi berhasil",
|
||||
please_enter_order_no: "Masukkan no. pesanan",
|
||||
please_enter_bill_no: "Masukkan no. tagihan",
|
||||
loading_data: "Memuat...",
|
||||
loading_mask: "memuat....",
|
||||
no_country: "Negara tidak tersedia",
|
||||
@ -270,6 +342,16 @@
|
||||
loadingConfig: false,
|
||||
ordering: false,
|
||||
activeOrderKey: "",
|
||||
autoVerifyOpen: false,
|
||||
autoVerifyLocked: false,
|
||||
autoVerifyStatusText: "",
|
||||
autoVerifyStatusType: "",
|
||||
autoVerifyForm: {
|
||||
orderNo: "",
|
||||
transferAmount: "",
|
||||
transferType: "BINANCE_PAY",
|
||||
billNo: ""
|
||||
},
|
||||
rechargeAmount: "",
|
||||
rechargeLocked: false,
|
||||
rechargeStatusText: "",
|
||||
@ -472,6 +554,10 @@
|
||||
return "/wallet/freight/ship";
|
||||
}
|
||||
|
||||
function endpointAutoVerify() {
|
||||
return "/app/h5/binance-recharge/verify";
|
||||
}
|
||||
|
||||
function endpointTransferHistory({ userId, type, searchId = "", lastId = "" }) {
|
||||
const query = new URLSearchParams({
|
||||
userId: String(userId || ""),
|
||||
@ -648,6 +734,16 @@
|
||||
status.classList.toggle("is-error", type === "error");
|
||||
}
|
||||
|
||||
function setAutoVerifyStatus(text = "", type = "") {
|
||||
state.autoVerifyStatusText = text;
|
||||
state.autoVerifyStatusType = type;
|
||||
const status = document.querySelector("#autoVerifyStatus");
|
||||
if (!status) return;
|
||||
status.textContent = text;
|
||||
status.hidden = !text;
|
||||
status.classList.toggle("is-error", type === "error");
|
||||
}
|
||||
|
||||
function setHistoryStatus(text = "", type = "") {
|
||||
state.historyStatusText = text;
|
||||
state.historyStatusType = type;
|
||||
@ -672,6 +768,15 @@
|
||||
return String(value || "").replace(/\D/g, "").replace(/^0+(?=\d)/, "");
|
||||
}
|
||||
|
||||
function sanitizeMoneyAmount(value) {
|
||||
const raw = String(value || "").replace(/[^\d.]/g, "");
|
||||
const parts = raw.split(".");
|
||||
const integerPart = parts.shift() || "";
|
||||
const decimalPart = parts.join("").slice(0, 8);
|
||||
const normalizedInteger = integerPart.replace(/^0+(?=\d)/, "");
|
||||
return decimalPart ? `${normalizedInteger || "0"}.${decimalPart}` : normalizedInteger;
|
||||
}
|
||||
|
||||
function renderSearch() {
|
||||
const input = document.querySelector("#accountInput");
|
||||
const button = document.querySelector("#searchButton");
|
||||
@ -754,6 +859,43 @@
|
||||
renderProfileAvatar(state.profile, "#targetAvatar", "#targetAvatarFallback");
|
||||
}
|
||||
|
||||
function renderAutoVerify() {
|
||||
const card = document.querySelector("#autoVerifyCard");
|
||||
const form = document.querySelector("#autoVerifyForm");
|
||||
const toggle = document.querySelector("#autoVerifyToggle");
|
||||
const orderInput = document.querySelector("#autoOrderInput");
|
||||
const amountInput = document.querySelector("#autoAmountInput");
|
||||
const typeSelect = document.querySelector("#autoTransferType");
|
||||
const billInput = document.querySelector("#autoBillInput");
|
||||
const button = document.querySelector("#autoVerifyButton");
|
||||
const values = state.autoVerifyForm;
|
||||
const amount = Number(values.transferAmount);
|
||||
const canSubmit = Boolean(
|
||||
state.profile &&
|
||||
!state.autoVerifyLocked &&
|
||||
String(values.orderNo || "").trim() &&
|
||||
Number.isFinite(amount) &&
|
||||
amount > 0 &&
|
||||
String(values.billNo || "").trim()
|
||||
);
|
||||
|
||||
if (card) card.hidden = !state.profile;
|
||||
if (form) form.hidden = !state.autoVerifyOpen || !state.profile;
|
||||
if (toggle) {
|
||||
toggle.hidden = !state.profile;
|
||||
toggle.textContent = state.autoVerifyOpen ? message("close_auto_verify") : message("open_auto_verify");
|
||||
}
|
||||
if (orderInput && document.activeElement !== orderInput) orderInput.value = values.orderNo;
|
||||
if (amountInput && document.activeElement !== amountInput) amountInput.value = values.transferAmount;
|
||||
if (typeSelect && document.activeElement !== typeSelect) typeSelect.value = values.transferType;
|
||||
if (billInput && document.activeElement !== billInput) billInput.value = values.billNo;
|
||||
if (button) {
|
||||
button.disabled = !canSubmit;
|
||||
button.textContent = state.autoVerifyLocked ? message("verifying") : message("verify_recharge");
|
||||
}
|
||||
setAutoVerifyStatus(state.autoVerifyStatusText, state.autoVerifyStatusType);
|
||||
}
|
||||
|
||||
function renderCoinRecharge() {
|
||||
const card = document.querySelector("#coinRechargeCard");
|
||||
const input = document.querySelector("#coinAmountInput");
|
||||
@ -1073,6 +1215,7 @@
|
||||
renderBalance();
|
||||
renderSearch();
|
||||
renderTarget();
|
||||
renderAutoVerify();
|
||||
renderCoinRecharge();
|
||||
renderWhatsappModal();
|
||||
}
|
||||
@ -1225,6 +1368,15 @@
|
||||
state.searchLocked = true;
|
||||
state.profile = null;
|
||||
state.payProfile = null;
|
||||
state.autoVerifyOpen = false;
|
||||
state.autoVerifyForm = {
|
||||
orderNo: "",
|
||||
transferAmount: "",
|
||||
transferType: "BINANCE_PAY",
|
||||
billNo: ""
|
||||
};
|
||||
state.autoVerifyStatusText = "";
|
||||
state.autoVerifyStatusType = "";
|
||||
state.rechargeAmount = "";
|
||||
state.rechargeStatusText = "";
|
||||
state.rechargeStatusType = "";
|
||||
@ -1241,6 +1393,14 @@
|
||||
const profile = Array.isArray(result) ? result[0] : result;
|
||||
if (!profile || !pickProfileId(profile)) throw new Error(message("user_not_found"));
|
||||
state.profile = profile;
|
||||
state.autoVerifyForm = {
|
||||
orderNo: "",
|
||||
transferAmount: "",
|
||||
transferType: "BINANCE_PAY",
|
||||
billNo: ""
|
||||
};
|
||||
state.autoVerifyStatusText = "";
|
||||
state.autoVerifyStatusType = "";
|
||||
state.rechargeAmount = "";
|
||||
state.rechargeStatusText = "";
|
||||
state.rechargeStatusType = "";
|
||||
@ -1282,6 +1442,88 @@
|
||||
}
|
||||
}
|
||||
|
||||
async function verifyAutoRecharge(event) {
|
||||
if (event) event.preventDefault();
|
||||
if (state.autoVerifyLocked) return;
|
||||
|
||||
const values = state.autoVerifyForm;
|
||||
values.orderNo = String(document.querySelector("#autoOrderInput")?.value || values.orderNo || "").trim();
|
||||
values.transferAmount = sanitizeMoneyAmount(document.querySelector("#autoAmountInput")?.value || values.transferAmount);
|
||||
values.transferType = String(document.querySelector("#autoTransferType")?.value || values.transferType || "BINANCE_PAY");
|
||||
values.billNo = String(document.querySelector("#autoBillInput")?.value || values.billNo || "").trim();
|
||||
|
||||
const userId = pickProfileId(state.profile);
|
||||
const amount = Number(values.transferAmount);
|
||||
if (!userId) {
|
||||
const text = message("user_not_found");
|
||||
setAutoVerifyStatus(text, "error");
|
||||
showToast(text);
|
||||
renderAll();
|
||||
return;
|
||||
}
|
||||
if (!values.orderNo) {
|
||||
const text = message("please_enter_order_no");
|
||||
setAutoVerifyStatus(text, "error");
|
||||
showToast(text);
|
||||
renderAll();
|
||||
return;
|
||||
}
|
||||
if (!Number.isFinite(amount) || amount <= 0) {
|
||||
const text = message("please_enter_valid_amount");
|
||||
setAutoVerifyStatus(text, "error");
|
||||
showToast(text);
|
||||
renderAll();
|
||||
return;
|
||||
}
|
||||
if (!values.billNo) {
|
||||
const text = message("please_enter_bill_no");
|
||||
setAutoVerifyStatus(text, "error");
|
||||
showToast(text);
|
||||
renderAll();
|
||||
return;
|
||||
}
|
||||
|
||||
state.autoVerifyLocked = true;
|
||||
setAutoVerifyStatus(message("verifying"));
|
||||
renderAll();
|
||||
|
||||
try {
|
||||
const result = await requestGoJSON(endpointAutoVerify(), {
|
||||
method: "POST",
|
||||
body: {
|
||||
billNo: values.billNo,
|
||||
orderNo: values.orderNo,
|
||||
targetUserId: String(userId),
|
||||
transferAmount: values.transferAmount,
|
||||
transferType: values.transferType
|
||||
}
|
||||
}) || {};
|
||||
const gold = formatCoins(result.goldAmount || 0);
|
||||
const successText = `${message("auto_verify_success")}: ${gold} ${message("coins")}`;
|
||||
state.autoVerifyForm = {
|
||||
orderNo: "",
|
||||
transferAmount: "",
|
||||
transferType: "BINANCE_PAY",
|
||||
billNo: ""
|
||||
};
|
||||
resetHistoryCache();
|
||||
setAutoVerifyStatus(successText);
|
||||
showToast(successText);
|
||||
if (String(userId) === String(pickProfileId(state.selfProfile))) {
|
||||
await fetchCoinBalance();
|
||||
}
|
||||
if (state.historyOpen) fetchHistoryRecords();
|
||||
} catch (error) {
|
||||
console.error("Auto recharge verification failed:", error);
|
||||
const text = error.response?.errorMsg || error.message || message("failed_to_load");
|
||||
setAutoVerifyStatus(text, "error");
|
||||
showToast(text);
|
||||
} finally {
|
||||
state.autoVerifyLocked = false;
|
||||
renderAll();
|
||||
}
|
||||
}
|
||||
|
||||
async function rechargeCoins(event) {
|
||||
if (event) event.preventDefault();
|
||||
if (state.rechargeLocked) return;
|
||||
@ -1509,6 +1751,15 @@
|
||||
function changeTarget() {
|
||||
state.profile = null;
|
||||
state.payProfile = null;
|
||||
state.autoVerifyOpen = false;
|
||||
state.autoVerifyForm = {
|
||||
orderNo: "",
|
||||
transferAmount: "",
|
||||
transferType: "BINANCE_PAY",
|
||||
billNo: ""
|
||||
};
|
||||
state.autoVerifyStatusText = "";
|
||||
state.autoVerifyStatusType = "";
|
||||
state.rechargeAmount = "";
|
||||
state.rechargeStatusText = "";
|
||||
state.rechargeStatusType = "";
|
||||
@ -1704,8 +1955,36 @@
|
||||
setRechargeStatus("");
|
||||
renderCoinRecharge();
|
||||
});
|
||||
document.querySelector("#autoVerifyToggle")?.addEventListener("click", () => {
|
||||
state.autoVerifyOpen = !state.autoVerifyOpen;
|
||||
renderAutoVerify();
|
||||
if (state.autoVerifyOpen) window.setTimeout(() => document.querySelector("#autoOrderInput")?.focus(), 60);
|
||||
});
|
||||
document.querySelector("#autoOrderInput")?.addEventListener("input", (event) => {
|
||||
state.autoVerifyForm.orderNo = String(event.target.value || "");
|
||||
if (state.autoVerifyStatusText) setAutoVerifyStatus("");
|
||||
renderAutoVerify();
|
||||
});
|
||||
document.querySelector("#autoAmountInput")?.addEventListener("input", (event) => {
|
||||
const value = sanitizeMoneyAmount(event.target.value);
|
||||
state.autoVerifyForm.transferAmount = value;
|
||||
if (event.target.value !== value) event.target.value = value;
|
||||
if (state.autoVerifyStatusText) setAutoVerifyStatus("");
|
||||
renderAutoVerify();
|
||||
});
|
||||
document.querySelector("#autoTransferType")?.addEventListener("change", (event) => {
|
||||
state.autoVerifyForm.transferType = String(event.target.value || "BINANCE_PAY");
|
||||
if (state.autoVerifyStatusText) setAutoVerifyStatus("");
|
||||
renderAutoVerify();
|
||||
});
|
||||
document.querySelector("#autoBillInput")?.addEventListener("input", (event) => {
|
||||
state.autoVerifyForm.billNo = String(event.target.value || "");
|
||||
if (state.autoVerifyStatusText) setAutoVerifyStatus("");
|
||||
renderAutoVerify();
|
||||
});
|
||||
document.querySelector("#searchForm")?.addEventListener("submit", searchTarget);
|
||||
document.querySelector("#coinRechargeForm")?.addEventListener("submit", rechargeCoins);
|
||||
document.querySelector("#autoVerifyForm")?.addEventListener("submit", verifyAutoRecharge);
|
||||
document.querySelector("[data-change-target]")?.addEventListener("click", changeTarget);
|
||||
document.querySelector("[data-help-open]")?.addEventListener("click", () => setModalOpen("#helpModal", true));
|
||||
document.querySelector("[data-history-open]")?.addEventListener("click", () => openHistoryModal());
|
||||
|
||||
@ -33,7 +33,8 @@ body {
|
||||
}
|
||||
|
||||
button,
|
||||
input {
|
||||
input,
|
||||
select {
|
||||
font: inherit;
|
||||
}
|
||||
|
||||
@ -189,7 +190,8 @@ button {
|
||||
}
|
||||
|
||||
.search-card,
|
||||
.coin-recharge-card {
|
||||
.coin-recharge-card,
|
||||
.auto-verify-card {
|
||||
display: grid;
|
||||
gap: 14px;
|
||||
padding: 16px;
|
||||
@ -242,6 +244,76 @@ button {
|
||||
gap: 12px;
|
||||
}
|
||||
|
||||
.auto-verify-toggle {
|
||||
min-width: 64px;
|
||||
min-height: 34px;
|
||||
padding: 0 12px;
|
||||
border-radius: 999px;
|
||||
background: #e7fbf8;
|
||||
color: #0aa397;
|
||||
font-size: 12px;
|
||||
font-weight: 950;
|
||||
}
|
||||
|
||||
.auto-verify-form {
|
||||
display: grid;
|
||||
gap: 12px;
|
||||
}
|
||||
|
||||
.auto-field {
|
||||
display: grid;
|
||||
gap: 7px;
|
||||
min-width: 0;
|
||||
}
|
||||
|
||||
.auto-field span {
|
||||
color: #555b63;
|
||||
font-size: 12px;
|
||||
font-weight: 900;
|
||||
line-height: 1.2;
|
||||
}
|
||||
|
||||
.auto-field input,
|
||||
.auto-field select {
|
||||
width: 100%;
|
||||
min-width: 0;
|
||||
height: 44px;
|
||||
border: 1px solid #e4eeee;
|
||||
border-radius: 8px;
|
||||
outline: 0;
|
||||
padding: 0 12px;
|
||||
background: #fbfdfd;
|
||||
color: #24282e;
|
||||
font-size: 14px;
|
||||
font-weight: 850;
|
||||
}
|
||||
|
||||
.auto-field select {
|
||||
appearance: none;
|
||||
background-image:
|
||||
linear-gradient(45deg, transparent 50%, #7a7f87 50%),
|
||||
linear-gradient(135deg, #7a7f87 50%, transparent 50%);
|
||||
background-position:
|
||||
calc(100% - 18px) 19px,
|
||||
calc(100% - 13px) 19px;
|
||||
background-size:
|
||||
5px 5px,
|
||||
5px 5px;
|
||||
background-repeat: no-repeat;
|
||||
}
|
||||
|
||||
[dir="rtl"] .auto-field select {
|
||||
background-position:
|
||||
18px 19px,
|
||||
13px 19px;
|
||||
}
|
||||
|
||||
.auto-field input:focus,
|
||||
.auto-field select:focus {
|
||||
border-color: rgba(21, 189, 169, 0.7);
|
||||
box-shadow: 0 0 0 3px rgba(21, 189, 169, 0.12);
|
||||
}
|
||||
|
||||
.search-form input {
|
||||
width: 100%;
|
||||
min-width: 0;
|
||||
@ -301,6 +373,7 @@ button {
|
||||
|
||||
.search-form button,
|
||||
.coin-recharge-form button,
|
||||
.auto-verify-form button,
|
||||
.package-button,
|
||||
.mini-action {
|
||||
min-height: 44px;
|
||||
@ -322,8 +395,14 @@ button {
|
||||
padding: 0 14px;
|
||||
}
|
||||
|
||||
.auto-verify-form button {
|
||||
width: 100%;
|
||||
padding: 0 14px;
|
||||
}
|
||||
|
||||
.search-form button:disabled,
|
||||
.coin-recharge-form button:disabled,
|
||||
.auto-verify-form button:disabled,
|
||||
.package-button:disabled,
|
||||
.mini-action:disabled {
|
||||
opacity: 0.55;
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user